线程池介绍及创建线程池的4种方式
1. 什么是线程池
Java中的线程池是运用场景最多的并发框架,几乎所有需要异步或并发执行任务的程序
都可以使用线程池。在开发过程中,合理地使用线程池能够带来3个好处。
第一:降低资源消耗。通过重复利用已创建的线程降低线程创建和销毁造成的消耗。
第二:提高响应速度。当任务到达时,任务可以不需要等到线程创建就能立即执行。
第三:提高线程的可管理性。线程是稀缺资源,如果无限制地创建,不仅会消耗系统资源,
还会降低系统的稳定性,使用线程池可以进行统一分配、调优和监控。但是,要做到合理利用
线程池,必须对其实现原理了如指掌。
2.线程池作用
线程池是为突然大量爆发的线程设计的,通过有限的几个固定线程为大量的操作服务,减少了创建和销毁线程所需的时间,从而提高效率。
如果一个线程的时间非常长,就没必要用线程池了(不是不能作长时间操作,而是不宜。),况且我们还不能控制线程池中线程的开始、挂起、和中止。
3.线程池四种创建方式
Java通过Executors(jdk1.5并发包)提供四种线程池,分别为:
newCachedThreadPool创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。
newFixedThreadPool 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。
newScheduledThreadPool 创建一个定长线程池,支持定时及周期性任务执行。
newSingleThreadExecutor 创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。
4.案例演示:
newCachedThreadPool
创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。示例代码如下:
package com.company.emple4; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; /** * @author shkstart * @date 2019/6/10- 16:16 */ public class Test001 { public static void main(String[] args) { //1.创建可缓存的线程池,可重复利用 ExecutorService newExecutorService = Executors.newCachedThreadPool(); //创建了10个线程 for (int i = 0; i < 10; i++) { int temp = i; newExecutorService.execute(new Runnable() { @Override public void run() { System.out.println("threadName;"+Thread.currentThread().getName()+",i"+temp); } }); } } }
可以看到本来创建了10个线程池,这里只用了7个,因为newCachedThreadPool创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程
newFixedThreadPool
创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。
package com.company.emple4; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; /** * @author shkstart * @date 2019/6/10- 16:16 */ public class Test001 { public static void main(String[] args) { //1.创建可固定长度的线程池 ExecutorService newExecutorService = Executors.newFixedThreadPool(3); //创建了10个线程 for (int i = 0; i < 10; i++) { int temp = i; newExecutorService.execute(new Runnable() { @Override public void run() { System.out.println("threadName;"+Thread.currentThread().getName()+",i"+temp); } }); } } }
可以看到newFixedThreadPool创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。
newScheduledThreadPool
创建一个定长线程池,支持定时及周期性任务执行。延迟执行示例代码如下:
package com.company.emple4; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; import static java.util.concurrent.TimeUnit.*; /** * @author shkstart * @date 2019/6/10- 16:16 */ public class Test001 { public static void main(String[] args) { //1.创建可定时线程池 ScheduledExecutorService newScheduledThreadPool = Executors.newScheduledThreadPool(5); for (int i = 0; i < 10; i++) { final int temp = i; newScheduledThreadPool.schedule(new Runnable() { public void run() { System.out.println("i:" + temp); } }, 3, TimeUnit.SECONDS); } } }
表示延迟3秒执行。
newSingleThreadExecutor
创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。示例代码如下:
package com.company.emple4; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; import static java.util.concurrent.TimeUnit.*; /** * @author shkstart * @date 2019/6/10- 16:16 */ public class Test001 { public static void main(String[] args) { //1.创建单线程 ExecutorService newSingleThreadExecutor = Executors.newSingleThreadExecutor(); for (int i = 0; i < 10; i++) { final int index = i; newSingleThreadExecutor.execute(new Runnable() { @Override public void run() { System.out.println("index:" + index); try { Thread.sleep(200); } catch (Exception e) { // TODO: handle exception } } }); } newSingleThreadExecutor.shutdown(); } }
注意: 结果依次输出,相当于顺序执行各个任务。当shutdown时停止线程