不接受新任务,但是处理已经在阻塞队列的任务
高3位全是0,就是SHUTDOWN状态
STOP
不接受新任务,也不处理阻塞队列里的任务,并且会中断正在处理的任务
所以高3位是001,就是STOP状态
TIDYING
所有任务都被中止,workerCount是0,线程状态转化为TIDYING并且调用terminated()钩子方法
所以高3位是010,就是TIDYING状态
TERMINATED
terminated()钩子方法已经完成
所以高3位是110,就是TERMINATED状态
3.部分方法介绍
runStateOf(int c)
实时获取runState的方法
private static int runStateOf(int c) { return c & ~CAPACITY; } ~CAPACITY ~是按位取反的意思 &是按位与的意思 而CAPACITY是,高位3个0,低29位都是1,所以是 000 11111 11111111 11111111 11111111 取反的话就是 111 00000 00000000 00000000 00000000 传进来的c参数与取反的CAPACITY进行按位与操作 1、低位29个0进行按位与,还是29个0 2、高位3个1,既保持c参数的高3位 既高位保持原样,低29位都是0,这也就获得了线程池的运行状态runStateworkerCountOf(int c)
获取线程池的当前有效线程数目
private static int workerCountOf(int c) { return c & CAPACITY; } CAPACITY的32位2进制是 000 11111 11111111 11111111 11111111 用入参c跟CAPACITY进行按位与操作 1、低29位都是1,所以保留c的低29位,也就是有效线程数 2、高3位都是0,所以c的高3位也是0 这样获取出来的便是workerCount的值
ctlOf(int rs, int wc)
原子整型变量ctl的初始化方法
//结合这几句代码来看 private static final int RUNNING = -1 << COUNT_BITS; private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0)); private static int ctlOf(int rs, int wc) { return rs | wc; } RUNNING是 111 00000 00000000 00000000 00000000 ctlOf是将rs和wc进行按位或的操作 初始化的时候是将RUNNING和0进行按位或 0的32位2进制是 00000000 00000000 00000000 00000000 所以初始化的ctl是 111 00000 00000000 00000000 00000000 核心方法源码分析execute(Runnable command)方法
public void execute(Runnable command) { //需要执行的任务command为空,抛出空指针异常 if (command == null) // 1 throw new NullPointerException(); /* *执行的流程实际上分为三步 *1、如果运行的线程小于corePoolSize,以用户给定的Runable对象新开一个线程去执行 * 并且执行addWorker方法会以原子性操作去检查runState和workerCount,以防止当返回false的 * 时候添加了不应该添加的线程 *2、 如果任务能够成功添加到队列当中,我们仍需要对添加的线程进行双重检查,有可能添加的线程在前 * 一次检查时已经死亡,又或者在进入该方法的时候线程池关闭了。所以我们需要复查状态,并有有必 * 要的话需要在停止时回滚入列操作,或者在没有线程的时候新开一个线程 *3、如果任务无法入列,那我们需要尝试新增一个线程,如果新建线程失败了,我们就知道线程可能关闭了 * 或者饱和了,就需要拒绝这个任务 * */ //获取线程池的控制状态 int c = ctl.get(); // 2 //通过workCountOf方法算workerCount值,小于corePoolSize if (workerCountOf(c) < corePoolSize) { //添加任务到worker集合当中 if (addWorker(command, true)) return; //成功返回 //失败的话再次获取线程池的控制状态 c = ctl.get(); } /* *判断线程池是否正处于RUNNING状态 *是的话添加Runnable对象到workQueue队列当中 */ if (isRunning(c) && workQueue.offer(command)) { // 3 //再次获取线程池的状态 int recheck = ctl.get(); //再次检查状态 //线程池不处于RUNNING状态,将任务从workQueue队列中移除 if (! isRunning(recheck) && remove(command)) //拒绝任务 reject(command); //workerCount等于0 else if (workerCountOf(recheck) == 0) // 4 //添加worker addWorker(null, false); } //加入阻塞队列失败,则尝试以线程池最大线程数新开线程去执行该任务 else if (!addWorker(command, false)) // 5 //执行失败则拒绝任务 reject(command); }我们来说一下上面这个代码的流程:
1、首先判断任务是否为空,空则抛出空指针异常
2、不为空则获取线程池控制状态,判断小于corePoolSize,添加到worker集合当中执行,
如成功,则返回