赞
踩
目录
2、newFixedThreadPool(fixed:固定的)
5、newSingleThreadScheduledExecutor
以下是使用 Executors框架去创建的线程池,是Java内置的线程池,已经设好了相应的参数。
用法:ExecutorService executorService = Executors.newFixedThreadPool(2);
通过Executor框架对线程池的构建,都是基于 ThreadpoolExecutor 构造方法来构建的。
作用:创建一个可根据需要创建新线程的线程池,但是在以前构造的线程可用时将重用它们,并在需要时使用提供的 ThreadFactory 创建新线程。整个线程池的线程数量并不固定,会随着需要来进行调整变化。该线程池使用同步队列 SynchronousQueue,该队列没有容量。
特征:
(1)线程池中数量没有核心线程,并且非核心线程数量不固定,没有上限,可达到最大值(Interger. MAX_VALUE)。
(2)线程池中的线程可进行缓存重复利用和回收(回收默认时间为1分钟,线程空闲时间超过60秒就会被回收)
(3)当线程池中,没有可用线程,会重新创建一个线程(会维持至少有一个空闲线程在线程池中)
(4)使用的是SynchronousQueue队列,只能存储一个任务
(5)60秒后将空闲线程关闭后,当线程池内线程为0时会自动关闭线程池
(6)初始化线程大小为0
创建方式:
(1)Executors.newCachedThreadPool();
(2)Executors.newCachedThreadPool(ThreadFactory threadFactory);
源码:
- public static ExecutorService newCachedThreadPool() {
- /*
- * 0:表示核心线程数为0
- * Integer.MAX_VALUE:表示最大线程数为Integer.MAX_VALUE
- * 60L:表示线程空闲时间为60秒,当线程数量超过核心线程数时,超过的空闲线程如果空闲时间超过60秒就会被回收,因为这个线程池的核心线程数量设置的为0,所以这个线程池中所有的线程只要是空闲时间超过了60s,都会被回收
- * TimeUnit.SECONDS:表示秒为时间单位
- * new SynchronousQueue<Runnable>():表示线程池中使用的阻塞队列为同步队列
- */
- return new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue<Runnable>());
- }
-
- public static ExecutorService newCachedThreadPool(ThreadFactory threadFactory) {
- /*
- * 0:表示核心线程数为0
- * Integer.MAX_VALUE:表示最大线程数为Integer.MAX_VALUE
- * 60L:表示线程空闲时间为60秒
- * TimeUnit.SECONDS:表示秒为时间单位
- * new SynchronousQueue<Runnable>():表示线程池中使用的阻塞队列为同步队列
- * threadFactory:表示线程工厂
- */
- return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
- 60L, TimeUnit.SECONDS,
- new SynchronousQueue<Runnable>(),
- threadFactory);
- }
执行流程:
1. 没有核心线程,直接向 SynchronousQueue 中提交任务。SynchronousQueue内部没有容器,该队列不会保留任务,任务达到后直接创建线程。
2. 如果有空闲线程,就去取出任务执行;如果没有空闲线程,就新建一个
3. 执行完任务的线程有 60 秒生存时间,如果在这个时间内可以接到新任务,就可以继续活下去,否则就被回收
适用场景:
作用:创建一个可重用固定线程数的线程池,以无界队列方式来运行这些线程,该线程池的线程数在创建时就被固定了,不可以扩大。在任意时间点,在大多数线程会处于处理任务的活动状态。如果在所有线程处于活动状态时提交附加任务,则在有可用线程之前,附加任务将在队列中等待。如果在线程关闭前的执行期间由于失败而导致任何线程终止,那么一个新线程将代替它执行后续的任务(如果需要)。在某个线程被显式地关闭之前,池中的线程将一直存在,即使线程一直处在空闲状态且队列为空,也不会被回收,直到调用shutdown。该线程池使用无界队列 LinkedBlockingQueue,该队列的最大容量为 Integer.MAX_VALUE,可以认为是无界的。因为不可以扩大线程数,所以也就不存在回收线程。
特征:
(1)FixedThreadPool 的核心线程数和最大线程数都是指定值,也就是说当线程池中的线程数超过核心线程数后,任务都会被放到阻塞队列中。该线程池的核心线程数量和最大线程数量是一样的,即全部都为核心线程。
(2)FixedThreadPool选用的阻塞队列是 LinkedBlockingQueue,使用的是默认容量 Integer.MAX_VALUE, 相当于没有上限
(3)线程池中的线程处于一定的量,可以很好的控制线程的并发量
(4)线程可以重复被使用,在线程被显示关闭之前,都将一直存在
(5)初始化时该线程池中的线程数就定了,是固定的,不可以扩大
(6)当线程处于空闲,且任务队列为空时,线程池也不会关闭
创建方式:
(1)Executors.newFixedThreadPool(int nThreads);//nThreads为线程的数量
(2)Executors.newFixedThreadPool(int nThreads,ThreadFactory threadFactory);//nThreads为线程的数量,threadFactory创建线程的工厂方式
源码:
- // 该线程池的最大线程数量和核心线程数量是一样的
- public static ExecutorService newFixedThreadPool(int nThreads) {
- /**
- * nThreads:表示线程池中核心线程数量
- * nThreads:表示线程池中最大线程数量
- * 0L:表示线程池中空闲线程的存活时间,0表示当线程数量超过线程池的核心线程数后,超过的线程如果空闲时间超过0就会被回收,这也就说明该线程池的线程数量是不会超过nThreads的,超过的空闲线程就会被回收。但是如果没有超过核心线程数量,空闲线程就可以一直存活,除非显式地关闭线程
- * TimeUnit.MILLISECONDS:表示空闲线程的存活时间的单位
- * new LinkedBlockingQueue<Runnable>():表示线程池中的任务队列使用的是无界队列LinkedBlockingQueue
- */
- return new ThreadPoolExecutor(nThreads, nThreads,
- 0L, TimeUnit.MILLISECONDS,
- new LinkedBlockingQueue<Runnable>());
- }
-
- // 默认情况下该线程池地最大线程数量和核心线程数量都是1,说明该线程池中只有一个线程在工作
- public static ExecutorService newSingleThreadExecutor() {
- /**
- * 1:表示线程池中核心线程数量
- * 1:表示线程池中最大线程数量
- * 0L:表示线程池中空闲线程的存活时间,0表示当线程数量超过线程池的核心线程数后,超过的线程如果空闲时间超过0就会被回收,这也就说明该线程池的线程数量是不会超过nThreads的,超过的空闲线程就会被回收。但是如果没有超过核心线程数量,空闲线程就可以一直存活,除非显式地关闭线程
- * TimeUnit.MILLISECONDS:表示空闲线程的存活时间的单位
- * new LinkedBlockingQueue<Runnable>():表示线程池中的任务队列使用的是无界队列LinkedBlockingQueue
- */
- return new FinalizableDelegatedExecutorService
- (new ThreadPoolExecutor(1, 1,
- 0L, TimeUnit.MILLISECONDS,
- new LinkedBlockingQueue<Runnable>()));
- }
执行流程:
1. 线程数少于核心线程数,也就是设置的线程数时,新建线程执行任务
2. 线程数等于核心线程数后,将任务加入阻塞队列
3. 由于队列容量非常大,可以一直添加
4. 执行完任务的线程反复去队列中取任务执行
适用场景:
主要适用于固定大小的线程池,因为它是无界的阻塞队列,那么线程池中的线程不会扩大,适用与可以预测线程数的场景中,或者服务器的负载很高,为了资源的合理利用,需要对线程数量进行严格控制的场景中。
作用:创建一个使用单个 worker 线程的 线程池,即该线程池只会有一个线程处于活动状态,所以任务只能一个一个被执行。以无界队列方式来运行该线程。(注意,如果因为在关闭前的执行期间出现失败而终止了此单个线程,一个新线程将代替它执行后续的任务)。可保证顺序地执行各个任务,并且在任意给定的时间不会有多个线程是活动的。该线程池使用无界队列 LinkedBlockingQueue,该队列的最大容量为 Integer.MAX_VALUE,可以认为是无界的。
特征:
(1)线程池中最多执行1个线程,之后提交的线程活动将会排在队列中以此执行
(2)该线程池是一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行
(3)SingleThreadExecutor选用的阻塞队列是 LinkedBlockingQueue,使用的是默认容量 Integer.MAX_VALUE, 相当于没有上限
(4)newSingleThreadExecutor返回的是一个经过代理的ExecutorService,不能转换为ThreadPoolExecutor,这也就意味着它只有一些ExecutorService的基本方法
(5)SingleThreadExecutor与单独new出来的Thread区别在于,单独new出来的Thread任务结束之后线程也就会随着结束,而且不可以submit提交任务到队列
创建方式:
(1)Executors.newSingleThreadExecutor() ;
(2)Executors.newSingleThreadExecutor(ThreadFactory threadFactory);// threadFactory创建线程的工厂方式
源码:
- public static ExecutorService newSingleThreadExecutor() {
- /**
- * 1(corePoolSize):表示线程池中的核心线程数量
- * 1:表示线程池的最大线程数量
- * 0L(keepAliveTime):表示线程池中超过corePoolSize数目的空闲线程最大存活时间,该线程池是值得核心线程数量为1,所以只要是线程池中的线程数量超过1,该空闲线程就会被回收
- * TimeUnit.MILLISECONDS:参数keepAliveTime的时间单位
- * new LinkedBlockingQueue<Runnable>():一个阻塞队列,用来存储等待执行的任务
- */
- return new FinalizableDelegatedExecutorService
- (new ThreadPoolExecutor(1, 1,
- 0L, TimeUnit.MILLISECONDS,
- new LinkedBlockingQueue<Runnable>()));
- }
-
- public static ExecutorService newSingleThreadExecutor(ThreadFactory threadFactory) {
- /**
- * 1(corePoolSize):表示线程池中的核心线程数量
- * 1:表示线程池的最大线程数量
- * 0L(keepAliveTime):表示线程池中超过corePoolSize数目的空闲线程最大存活时间,该线程池是值得核心线程数量为1,所以只要是线程池中的线程数量超过1,该空闲线程就会被回收
- * TimeUnit.MILLISECONDS:参数keepAliveTime的时间单位
- * new LinkedBlockingQueue<Runnable>():一个阻塞队列,用来存储等待执行的任务
- * threadFactory:线程工厂,用来创建线程
- */
- return new FinalizableDelegatedExecutorService
- (new ThreadPoolExecutor(1, 1,
- 0L, TimeUnit.MILLISECONDS,
- new LinkedBlockingQueue<Runnable>(),
- threadFactory));
- }
适用场景:
适用于需要保证任务被按顺序执行,并且在任何时候都不会出现多个线程的情况。
作用: 创建一个线程池,它可以实现在给定延迟后运行命令或者定期地执行。该线程池使用延迟阻塞队列 DelayedWorkQueue。
特征:
(1)线程池中具有指定数量的线程,即便是空线程也将保留
(2)可定时或者延迟执行线程活动
创建方式:
(1)Executors.newScheduledThreadPool(int corePoolSize);// corePoolSize线程的个数
(2)newScheduledThreadPool(int corePoolSize, ThreadFactory threadFactory);// corePoolSize线程的个数,threadFactory创建线程的工厂
源码:
- public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
- // corePoolSize:表示线程池中的核心线程数
- return new ScheduledThreadPoolExecutor(corePoolSize);
- }
-
- public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize, ThreadFactory threadFactory) {
- // corePoolSize:表示线程池中的核心线程数
- // threadFactory:线程工厂,用于创建线程
- return new ScheduledThreadPoolExecutor(corePoolSize, threadFactory);
- }
作用: 创建一个单线程执行程序,它可实现在给定延迟后运行命令或者定期地执行。该线程池使用延迟阻塞队列 DelayedWorkQueue。
特征:
(1)线程池中最多执行1个线程,之后提交的线程活动将会排在队列中以此执行
(2)可定时或者延迟执行线程活动
创建方式:
(1)Executors.newSingleThreadScheduledExecutor() ;
(2)Executors.newSingleThreadScheduledExecutor(ThreadFactory threadFactory) ;//threadFactory创建线程的工厂
源码:
- public static ScheduledExecutorService newSingleThreadScheduledExecutor() {
- return new DelegatedScheduledExecutorService
- (new ScheduledThreadPoolExecutor(1));
- }
-
- public static ScheduledExecutorService newSingleThreadScheduledExecutor(ThreadFactory threadFactory) {
- return new DelegatedScheduledExecutorService
- (new ScheduledThreadPoolExecutor(1, threadFactory));
- }
特征:
(1)该方法会根据你的CPU核数来创建线程个数,也可指定线程数
(2)newWorkStealingPool其内部使用的是ForkJoinPool,在任务全部执行完之后该线程池会自动关闭
适用场景:
创建一个拥有多个任务队列的线程池,可以减少连接数,创建当前可用cpu数量的线程来并行执行,适用于大耗时的操作,可以并行来执行
在《阿里巴巴 Java 开发手册》“并发处理”这一章节,明确指出线程资源必须通过线程池提供,不允许在应用中自行显式创建线程。
为什么呢?
另外,《阿里巴巴 Java 开发手册》中强制线程池不允许使用 Executors 去创建,而是通过 ThreadPoolExecutor 构造函数的方式,这样的处理方式让写的同学更加明确线程池的运行规则,规避资源耗尽的风险。
Executors 返回线程池对象的弊端如下(后文会详细介绍到):
所以不建议用下面这些方法创建线程池,还是直接使用ThreadPoolExecutor的构造方法,自己制定相应的参数来创建。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。