主要的成员变量:
private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));
private static final int COUNT_BITS = Integer.SIZE - 3;
private static final int CAPACITY = (1 << COUNT_BITS) - 1;
ctl:保存线程池状态和线程池有效数量控制的字段,使用前Integer类型来保存,高三位保存状态(runState),低29位保存线程池内有效线程数(worerkCount);
COUNT_BITS:Integer.SIZE=32,所以是29;
CAPACITY:最大的线程容量,即低29位最多能保存的线程数,1^29-1,低29位全为1
1^29-1,为什么会是低29位全为1?
1左移29位是100000...(29个零),二进制的减法是从低位开始减,不够向高位借1变成2(十进制时,高位借1后也是加10),用2-1=1。所以减完变成最高位是0,其余都是1了。
ctl的相关方法
private static int runStateOf(int c) { return c & ~CAPACITY; }
private static int workerCountOf(int c) { return c & CAPACITY; }
private static int ctlOf(int rs, int wc) { return rs | wc; }
runStateOf:获取运行状态
workerCountOf:获取活动线程数
ctlOf:获取运行状态和活动线程数的值
//高三位是111,-1二进制8位是11111111
private static final int RUNNING = -1 << COUNT_BITS;
//高三位是000
private static final int SHUTDOWN = 0 << COUNT_BITS;
//高三位是001
private static final int STOP = 1 << COUNT_BITS;
//高三位是010
private static final int TIDYING = 2 << COUNT_BITS;
//高三位是011
private static final int TERMINATED = 3 << COUNT_BITS;
线程池的5中状态:
RUNNING:线程池处于该状态时,可以接收任务,并可以对已添加的任务进行处理。线程池一旦被创建,初始状态就是该状态,并且线程数为0;
SHUTDOWM:处于该状态,线程池不再接收新任务,但可以处理已添加的任务,当调用shutdown()方法时,状态由RUNNING变为SHUTDOWN;
STOP:线程池处于该状态时,不再接收新任务,不会处理已存在的任务,且中断正在执行的任务。当调用shotdownNow()时,状态由RUNNING/SHUTDOWN变成STOP;
TIDYING:当所有任务已经终止,并且ctl中的数量为0,则会变成该状态。该状态下会执行terminated()方法,该方法是一个钩子方法,当用户想在TIDYING状态时做相应的处理,可以重载该钩子方法。
当线程池状态为SHUTDOWN,阻塞队列为空并且正在执行的任务为0时,就会由SHUTDOWN变为TIDYING。当状态为STOP,线程池的执行数量为空时,也会变为该状态。
TERMINATED:线程池彻底终止就会进入该状态,当线程池处于TIDYING状态,并调用terminated()方法时,就进入该状态。
根据以上综合可知,进入TERMINATED状态需满足以下条件:
- 线程池状态不是RUNNING方法;
- 如果线程是SHUTDOWN并且workerQueue为空;
- 线程池中执行的任务数量为0;
- 设置TIDYING状态成功;
线程池的具体实现:
默认实现:ThreadPoolExecutor;定时线程池实现:ScheduledThreadExecutor