前言
线程池是并发编程中最重要的应用之一,使用线程池可以防止大量的创建和销毁线程的过程,可以节省很多的内存空间,提高程序的响应率和cpu的利用率,并且也可以对线程进行统一管理和监控。这里将分几篇文章介绍一下线程池的源码分析。本篇是分析ThreadPoolExecutor中的ctl变量。并且去写了线程中的
ctl变量
源码中的解释
ThreadPoolExecutor中有个字段是ctl,具体来说是对线程池的运行状态和池子中的有效线程数量的控制的一个字段变量,我们可以看看源码中的解释:
1 | /** |
可以看到ctl是AtomicInteger对象,里面的操作都是基于CAS的原子操作。一个ctl变量包含两部分信息,因为int类型的变量是32位的,所以高3位表示线程池的运行状态(runState),低29位表示线程池中有效线程数(workerCount)。
所以,当我们知道了线程池中的运行状态和有效线程数,就可以通过ctlOf方法计算出ctl的值:
1 | private static int ctlOf(int rs, int wc) { return rs | wc; } |
反过来,我们也可以通过ctl计算出runState和workerCount的值:
1 | private static int runStateOf(int c) { return c & ~CAPACITY; } |
其中CAPACITY是(2^29)-1, 也就是高三位是0,低29位是1的一个int类型的数字常量。这个CAPACITY表示线程池中有效线程的上限值。这个值的计算过程:
1 | private static final int COUNT_BITS = Integer.SIZE - 3; // 29 |
线程池的状态
线程池中有五种状态:
1 | // runState is stored in the high-order bits |
其中COUNT_BITS的值是29,在后边的源码分析过程中,我们其实只需要知道这几个状态是逐渐递增的即可。比如说在源码中看到 rs < SHUTDOWN 其实就是表示此时线程池的运行状态是RUNNING。
五种状态的解释:
(1)RUNNING:运行状态,能接受提交新的任务,并且也能处理阻塞队列中的任务。
(2)SHUTDOWN:关闭状态,不再接受新提交的任务,但是可以处理阻塞在任务队列中已保存的任务。在线程池处于RUNNING状态的时候,调用shutdown方法线程池即变为此状态。
(3)STOP:停止状态,不再接受新提交的任务,也不会处理阻塞队列中已保存的任务,并且会中断正在处理的任务,在线程池处于RUNNING状态或者SHUTDOWN状态的时候,调用shutdownNow方法线程池即进入该状态。
(4)TIDYING:清理状态,所有的任务都已经终止,workerCount有效线程数量为0,线程池进入该状态后调用terminated方法可以使线程池进入Terminated状态。当线程池处于SHUTDOWN状态时,如果此后线程池中没有线程并且阻塞队列中没有要执行的任务,就会进入到这个状态;当线程池处于STOP状态时,如果此时线程池中没有线程了,线程池会进入该状态。
(5)TERMINATED:terminated()方法执行之后会进入该状态。
其他字段参数
1 |
|
下一章
下一章将会去写一下ThreadPoolExecutor的构造函数和核心参数。