引用
如果看了ThreadPoolExecutor
的源码,看到了第一个变量便是一个AtomicInteger
类型的ctl
private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));
用来描述线程池的状态(pool control state)
本文就来分析一下这个ctl。
相关代码
与ctl的相关代码如下:
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;
// runState is stored in the high-order bits
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;
// Packing and unpacking ctl
//得到运行状态
private static int runStateOf(int c) { return c & ~CAPACITY; }
//得到工作线程数量
private static int workerCountOf(int c) { return c & CAPACITY; }
//初始化ctl
private static int ctlOf(int rs, int wc) { return rs | wc; }
观察线程池运行状态,总共有5个状态,因此可以用3个bit来表示,也就是用整数(Integer)的高3位来表示,低29位来表示工作线程数量。(最多可以表示2^29-1 : 536870911,有5亿多了)。
原理浅析
下面通过代码来看是怎么实现的
为了好分析,本人改写了一下toBinaryString()
方法:
private String toBinaryString(int i){
final char[] digits = {
'0' , '1' , '2' , '3' , '4' , '5' ,
'6' , '7' , '8' , '9' , 'a' , 'b' ,
'c' , 'd' , 'e' , 'f' , 'g' , 'h' ,
'i' , 'j' , 'k' , 'l' , 'm' , 'n' ,
'o' , 'p' , 'q' , 'r' , 's' , 't' ,
'u' , 'v' , 'w' , 'x' , 'y' , 'z'
};
int shift = 1;
char[] buf = new char[32];
for (int j=0;j<buf.length;j++){
buf[j] = '0';
}
int charPos = 32;
int mask = 1;
do {
buf[--charPos] = digits[i & mask];
i >>>= shift;
} while (i != 0);
return new String(buf);
}
当然也有更简单的实现方式,但这不是重点。
然后写了一个测试用例:
@Test
public void testNumber(){
final int COUNT_BITS = Integer.SIZE - 3;
final int CAPACITY = (1 << COUNT_BITS) - 1;
// runState is stored in the high-order bits
final int RUNNING = -1 << COUNT_BITS;
final int SHUTDOWN = 0 << COUNT_BITS;
final int STOP = 1 << COUNT_BITS;
final int TIDYING = 2 << COUNT_BITS;
final int TERMINATED = 3 << COUNT_BITS;
System.out.println(CAPACITY);
System.out.println("CAPACITY :"+toBinaryString(CAPACITY));
System.out.println("RUNNING :"+toBinaryString(RUNNING));
System.out.println("SHUTDOWN :"+toBinaryString(SHUTDOWN));
System.out.println("STOP :"+toBinaryString(STOP));
System.out.println("TIDYING :"+toBinaryString(TIDYING));
System.out.println("TERMINATED:"+toBinaryString(TERMINATED));
}
输出:
536870911
CAPACITY :00011111111111111111111111111111
RUNNING :11100000000000000000000000000000
SHUTDOWN :00000000000000000000000000000000
STOP :00100000000000000000000000000000
TIDYING :01000000000000000000000000000000
TERMINATED:01100000000000000000000000000000
然后再来看这3个方法就会很容易理解了,主要是一些位操作:
//得到运行状态
private static int runStateOf(int c) {
return c & ~CAPACITY; //c 与 CAPACITY的取反
}
//得到工作线程数量
private static int workerCountOf(int c) {
return c & CAPACITY;
}
//初始化ctl
private static int ctlOf(int rs, int wc) {
return rs | wc;
}