上面這段代碼一直在用,面試的時候也經常被問到,卻從未深究過,不知道線程池到底是怎麼回事,今天看看源代碼,一探其究竟 線程池主要控制的狀態是ctl,它是一個原子的整數,其包含兩個概念欄位: workerCount:有效的線程數量 runState:線程池的狀態 為了在一個整型值裡面包含這兩個欄位,我們 ...
上面這段代碼一直在用,面試的時候也經常被問到,卻從未深究過,不知道線程池到底是怎麼回事,今天看看源代碼,一探其究竟
線程池主要控制的狀態是ctl,它是一個原子的整數,其包含兩個概念欄位:
- workerCount:有效的線程數量
- runState:線程池的狀態
為了在一個整型值裡面包含這兩個欄位,我們限制workerCount最多2的29次方減1
runState的值有這樣幾種:
- RUNNING: 接受新的任務,並處理隊列中的任務
- SHUTDOWN:不接受新的任務,繼續處理隊列中的任務
- STOP: 不接受新的任務,也不處理隊列中的任務,並且中斷正在處理的任務
- TIDYING: 所有任務都結束了,workerCount是0,通過調用terminated()方法轉換狀態
- TERMINATED:terminated()方法已經完成
狀態之間的轉換時這樣的:
RUNNING -> SHUTDOWN
調用shutdown()方法,或者隱式的調用finalize()方法
(RUNNING or SHUTDOWN) -> STOP
調用shoutdownNow()方法
SHUTDOWN -> TIDYING
當隊列和池都是空的時候
STOP -> TIDYING
當池是空的時候
TIDYING -> TERMINATED
當terminated()方法調用完成時
Integer.SIZE=31
Integer.SIZE - 3 = 29
所以,COUNT_BITS = 29
高3位存儲runState
接下來看最複雜的那個構造方法
參數詳解
- corePoolSize:保持在池中的線程數(PS:即使它們處於空閑狀態)
- maximumPoolSize:池中允許的最大線程數
- keepAliveTime:當線程數超過核心線程數的時候,超出的線程的最大生存時間
- unit:keepAliveTime的單位
- workQueue:維護待處理的任務的隊列
- threadFactory:創建線程的工廠
1、如果正在運行的線程數少於核心線程數,則新建一個線程去運行這個任務
2、如果工作隊列沒有滿,則放到工作隊列中
3、如果工作隊列已滿(PS:workQueue.offer(command)返回false),則再新建線程
4、若線程數已經達到最大線程數則reject(command)
在前面execute方法中,有3處調用了addWork()方法
第一處,如果當前有效線程數少於核心線程數,則調用之,此時線程數的邊界是核心線程數
第二處,如果當前有效線程數超過核心線程數,並且將新任務放到隊列中,此時有效線程數是0,則創建一個新線程
第三處,如果當前有效線程數超過核心線程數,並且隊列已經放滿了,並且有效線程數小於最大線程數,此時調用以創建新線程,
當前的有效線程都在works裡面,而works裡面放的是Worker對象,接下來看Worker
前一步中,線程的start()方法,線程運行的時候執行run()方法,而Worker繼承Runnable並重新run()方法,run()方法又調用外部的runWorker()方法,所以,線上程池中新創建的線程運行時調用的是runWorker()方法
runWorker()方法迴圈的從隊列中取出任務並執行它。也就是說,池中所有的線程都是在創建的時候如果傳進來新任務,則先執行新任務,然後迴圈從隊列中取出任務並執行
接下來,看Executors中常見的幾種線程池的區別
可以看到
newSingleThreadExecutor:核心線程數和最大線程數都是1,隊列是LinkedBlockingQueue
newFixedThreadPool:核心線程數和最大線程數相等,超過核心線程數的空閑線程生存時間是0,隊列是LinkedBlockingQueue
newCachedThreadPool:核心線程數是0,最大線程數是Integer.MAX_VALUE,空閑線程生存時間是1min,隊列是SynchronousQueue