ThreadPoolExcutor源码流程图:(图片较大,下载再看比较方便)
线程池里的二进制奥秘
前言:
线程池的五种状态state (RUNNING 、SHUTDOWN 、STOP 、TIDYING 、TERMINATED )和线程池的工作线程数:workerCount,
这两个变量,可有通过一个变量ctl 转成二进制后而获得。
直接看线程池ThreadPoolExecutor 源码里,管理状态和工作线程数的代码
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;
private static final int RUNNING = -1 << COUNT_BITS;
private static final int SHUTDOWN = 0 << COUNT_BITS;
private static final int STOP = 1 << COUNT_BITS;
private static final int TIDYING = 2 << COUNT_BITS;
private static final int TERMINATED = 3 << COUNT_BITS;
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; }
Integer.size 为Integer 类型最大值的二进制的位数:32 (位),COUNT_BITS = 29 (位),为啥是要要减去3 ,拿个29 呢,因为它想用二进制高3 位来表示线程池的状态(state ),后面的29 位用来表示工作线程数量(workerCount )。
比如RUNNINGZ 状态是-1 左移29 位,即:
-1 的二进制算法,先取绝对值1 的二进制:00000000 00000000 00000001 ,再取反码:11111111 11111111 11111110
再取补码(加1 ):11111111 11111111 11111111 ,这就是-1 的二进制表示。
左移运算:-1<
各个state :
-1<
0<< 29 =000 00000 00000000 00000000 => SHUTDOWN
1 <
2 <
3 <
线程池就是这样用高三位来表示不同的状态。
所以状态还有这样的关系: RUNNINGZ < SHUTDOWN < STOP < TIDYING < TERMINATED
不管各个状态低29 位是啥,这个关系都不会变。
再看CAPACITY = (1<
即00100000 00000000 00000000 – 1 = 00011111 11111111 11111111 ,这是线程池最大容量线程数(536870911 ),
即是用1 到29 位可表示线程的数量,那么,ctl = state.高3 位+低29 位,如:
ctl =111 11111 11111111 11111111 ,表示线程池是RUNNINGZ 状态,且线程数为536870911 ;
ctl =000 00000 00000000 00000001 ,表示线程池是SHUTDOWN 状态,且线程数为1 ;
CAPACITY=536870911 ,表示线程池最大线程数容量为536870911 ,但这个最大数值可以忽略,
因为在实例化线程池的时候,已经通过传参数设置了核心线程数、允许最大线程数。
初始化为 ctl = new AtomicInteger(ctlOf (RUNNING, 0));
ctlOf (RUNNING, 0)参数中的0 ,意思是初始化线程池的线程数为0 。然后通过ctlOf做或运算,即:
111 00000 00000000 00000000 | 00000000 00000000 00000000 =111 00000 00000000 00000000
运算后的结果,把表示状态的高3 位、表示线程数的低29 位组合起来得到一个数ctl ,
下次拿到ctl 之后,就知道此时线程池的状态和线程数量了。
1、那么runStateOf(int c)方法具体是怎么知道线程池的状态的?
假设c = ctl.get() =001 00000 00000000 00000011 ,表示STOP 状态且还有3 个线程
CAPACITY =(1<
为啥要减1 呢?因为减1 后:
1 、把表示状态的高3 位给挪留出来了,值又可以表示线程池最大线程数。
2 、把表示线程数的低29 位变为了1 ,那~CAPACITY = 11100000 00000000 00000000 , 所以:
c &~CAPACITY =001 00000 00000000 00000011 & 11100000 00000000 00000000 =001 00000 00000000 00000000 ,
结果001 00000 00000000 00000000 保持c 的高3 位不变,把c 的低29 位全变成0,这就是获得线程池是STOP 状态
2、通过workerCountOf(int c)获取工作线程数,同上理
Original: https://www.cnblogs.com/incognitor/p/16401160.html
Author: 無名之徒
Title: 线程池:ThreadPoolExcutor源码阅读
原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/622645/
转载文章受原作者版权保护。转载请注明原作者出处!