線程池ThreadPoolExecutor里Control state,ctl參數的分析(一)
線程池
打開ThreadPoolExecutor的源代碼,第一個變數就是:
private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));
這是一個原子INT操作類,這個值非常有意思,表面上看,這是一個int值,按照一般的理解,代表一個數字,一種狀態,比如,0女1男,1開始2運行中3結束等等。
但是在ThreadPoolExecutor中,這一個數字卻代表了兩個概念:
1、 workerCount,有效的線程數。
2、 runState,線程池運行的狀態(具體文後再談)。
一般人看到這會有疑問(好吧,這其實是我的疑問,也是本篇文章的寫作初衷):
- 為什麼要用一個數字表達兩個概念?
- 如何用一個數字來表達兩個概念?
先說第一個問題。一般開發人員(比如我這樣的)遇到這種情況估計直接:
private int workerCount = 0;
private int runState = 0;
如果考慮線程安全的話,大不了用AtomicInteger就是。
但是大家要考慮到ThreadPoolExecutor是java.util.concurrent包中的線程池,是基礎類,也是對性能要求很高的並發包,在性能上儘可能做到極致,是大神們自然而然的選擇。所以能用一個數字解決的問題,就不再用兩個。一個int32位(4位元組),現在的內存白菜價,以前的內存可貴了~~
重點是第二個問題,很多人不明白一個數字是怎麼能表達兩個概念的(其實是我不明白)。
在一般程序員眼中,一個數字就是一個數字,但是在大神們的眼中,一個int數字則是一個32位的二進位啊!32個0、1的組合,可以搞出很多事情來。
來補補基礎課~~
比如數字15,32位二進位的表達就是:00000000000000000000000000001111。
二進位使用最高位作為符號位, 0正數, 1負數。
所以int的最大值的二進位就是01111111111111111111111111111111=2147483647
最小值10000000000000000000000000000000=-2147483648
我們可以輕易得出1=00000000000000000000000000000001
-1= 10000000000000000000000000000001
但其實計算機里不是這麼做的,這涉及二進位的原碼、反碼、補碼的表達方式,簡單地說:
-1的原碼:10000000000000000000000000000001
-1的反碼:符號位不變,其他位取反
-1的補碼:反碼+1
所以應該是:
原碼:10000000000000000000000000000001
反碼:11111111111111111111111111111110
補碼:11111111111111111111111111111111
計算機使用的是補碼。
線程池的運行狀態runState,狀態值只有固定的5個:-1,0,1,2,3(具體含義文後再談),其二進位表達為:
-1:11111111111111111111111111111111
0:00000000000000000000000000000000
1:00000000000000000000000000000001
2:00000000000000000000000000000010
3:00000000000000000000000000000011
但是大家注意,因為狀態值是固定的,所以用32位來表達其實是浪費了,實際只要3位就可以表達5個數字,即1個符號位,2個數值位
可以簡化為:
-1:111
0:000
1:001
2:010
3:011
所以大神們就決定ctl這個int值的32位二進位值中,前3個用來表示狀態值runState。
後面的32-3=29位,就用來表示workerCount線程數。
所以我們就得出了ThreadPoolExecutor類中第二個變數:
private static final int COUNT_BITS = Integer.SIZE - 3;
那麼也可以得出,線程數的最大值就是29個1:00011111111111111111111111111111= 536870911=2^29-1。
所以我們就得出了ThreadPoolExecutor類中第三個變數,線程池最大容量:
private static final int CAPACITY = (1 << COUNT_BITS) - 1;
至於如何構建ctl,如何從ctl獲取需要的runState、workerCount,下篇文章再分析。
※個人關於數據結構與演算法的一點學習筆記(一)
※總結對==、equals、hashCode的認識
TAG:Java個人學習心得 |