ThreadPoolExecutor参数详解
public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler) { if (corePoolSize < 0 || maximumPoolSize <= 0 || maximumPoolSize < corePoolSize || keepAliveTime < 0) throw new IllegalArgumentException(); if (workQueue == null || threadFactory == null || handler == null) throw new NullPointerException(); this.corePoolSize = corePoolSize; this.maximumPoolSize = maximumPoolSize; this.workQueue = workQueue; this.keepAliveTime = unit.toNanos(keepAliveTime); this.threadFactory = threadFactory; this.handler = handler; }
ThreadPoolExecutor参数解释
ThreadPoolExecutor总共有七个参数,每个参数都对线程池的性能有很大的的影响,线面就让我们来看一个各个参数的意思。
corePoolSize
-保留在池中的核心线程数(即使它们处于空闲状态),除非allowCoreThreadTimeOut
已设置
maximumPoolSize
-池中允许的最大线程数
keepAliveTime
-当线程数大于核心线程数数时,如果线程池中的最大线程数大于核心线程数,那么这个时间就是
(maximumPoolSize-corePoolSize)的线程在终止之前等待新任务的最长时间。
unit
-keepAliveTime
参数的时间单位
workQueue
-在执行任务之前用于保留任务的队列。该队列将仅保存Runnable
该execute
方法提交的任务。
threadFactory
-执行程序创建新线程时要使用的工厂
handler
-因为达到了线程界限和队列容量而在执行被阻止时使用的处理程序
1:当提交给线程池任务时,如果没有空闲线程执行任务并且当前线程池中的线程数少于corePoolSize,则创建新的线程执行任务。
2:当提交给线程池任务时,如果没有空闲线程执行任务并且当前线程池中的线程数等于corePoolSize,若workQueue未满时,则把任务放入workQueue中。
3:当提交给线程池任务时,如果没有空闲线程执行任务并且当前线程池中的线程数等于corePoolSize且小于maximumPoolSize时,若workQueue已满时,则创建新的线程执行任务。
(4)当提交给线程池任务时,如果没有空闲的线程执行该任务且阻塞队列已满同时池中的线程数等于maximumPoolSize,则根据构造函数中的handler指定的策略来拒绝新的任务。
注意,线程池并没有标记哪个线程是核心线程,哪个是非核心线程,线程池只关心核心线程的数量
拒绝策略(RejectedExecutionHandler)
拒绝策略总共有四种,都是ThreadPoolExecutor的内部类,可以RejectedExecutionHandler参考代码的实现类,代码很少,很容易能看懂;
static class | ThreadPoolExecutor.AbortPolicy 抛出的被拒绝任务的处理程序 RejectedExecutionException 。 |
---|---|
static class |
ThreadPoolExecutor.CallerRunsPolicy 拒绝任务的处理程序,直接在方法的调用线程中运行拒绝任务execute ,除非执行器已关闭,在这种情况下,该任务将被丢弃。 |
static class |
ThreadPoolExecutor.DiscardOldestPolicy 拒绝任务的处理程序,它丢弃最旧的未处理请求,然后重试execute ,除非执行器被关闭,在这种情况下,该任务将被丢弃。 |
static class |
ThreadPoolExecutor.DiscardPolicy 拒绝任务的处理程序,静默丢弃被拒绝的任务。 |
线程池的状态
注意这里指的是线程池的状态,而不是线程的状态。
线程池具有以下五种状态,当创建一个线程池时初始化状态为RUNNING
RUNNING | 允许提交并处理任务 |
---|---|
SHUTDOWN | 不允许提交新的任务,但是会处理完已提交的任务 |
STOP | 不允许提交新的任务,也不会处理阻塞队列中未执行的任务,并设置正在执行的线程的中断标志位 |
TIDYING | 所有任务执行完毕,池中工作的线程数为0,等待执行terminated()勾子方法 |
TERMINATED | terminated()勾子方法执行完毕 |
线程池的状态主要是有这一个变量来控制的,private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));
ctl主要用于存储线程池的工作状态以及池中正在运行的线程数。要在一个整型变量存储两个数据,只能将其一分为二。其中高3bit用于存储线程池的状态,低位的29bit用于存储正在运行的线程数。具体的解释可以参考源码的注释。
线程池状态变化
调用线程池的shutdown方法,将线程池由RUNNING(运行状态)转换为SHUTDOWN状态。
调用线程池的shutdownNow方法,将线程池由RUNNING或SHUTDOWN状态转换为STOP状态。
SHUTDOWN状态和STOP状态先会转变为TIDYING状态,最终都会变为TERMINATED。