系列目錄
- 【詳解】ThreadPoolExecutor原始碼閱讀(一)
- 【詳解】ThreadPoolExecutor原始碼閱讀(二)
- 【詳解】ThreadPoolExecutor原始碼閱讀(三)
執行緒數量的維護
執行緒池的大小有兩個重要的引數,一個是corePoolSize(核心執行緒池大小),另一個是maximumPoolSize(最大執行緒大小)。執行緒池主要根據這兩個引數對執行緒池中執行緒的數量進行維護。
需要注意的是,執行緒池建立之初是沒有任何可用執行緒的。只有在有任務到達後,才開始建立執行緒,並複用執行緒。
注:此圖不是狀態圖,不是說新增一個執行緒就直接到達corePoolSize狀態,而是要表示,一直新增執行緒直到達到corePoolSize。
註釋裡也寫的很清楚了:
(1)如果執行緒數未達核心數,則每接收一個任務就建立一個工作執行緒(這裡把Worker視為工作執行緒)來處理。
(2)如果執行緒數已達到核心數,那就把任務先放入佇列。等到有工作執行緒完成任務了,會自行從佇列中取任務做。
(3)如果任務無法放入佇列,如佇列是有界佇列,且已滿。那麼就會繼續建立工作執行緒來處理這個任務。注意,這裡的新執行緒已經不是核心執行緒了。
(4)如果執行緒數量已經達到maxPoolSize,這時候就是執行緒不能再建立了,任務也放不進佇列了,就得啟動reject策略。預設策略是AbortPolicy,也就是直接報異常。
public void execute(Runnable command) { //非空檢查 if (command == null) throw new NullPointerException(); //獲取執行緒池控制資訊 int c = ctl.get(); //通過workerCountOf方法獲取控制資訊內的工作執行緒數資訊 //如果小於核心執行緒數,執行addWorker方法 0 => corePoolSize if (workerCountOf(c) < corePoolSize) { //這個操作新增的是核心工作執行緒,且有初始任務 if (addWorker(command, true)) return; //如果操作成功直接返回 //由於addWorker操作對工作執行緒數,可能有所更改,故重新獲取控制資訊 c = ctl.get(); } //新增核心執行緒失效後 //如果執行緒池處於執行狀態,且任務成功加入阻塞佇列 corePoolSize => corePoolSize if (isRunning(c) && workQueue.offer(command)) { //再次檢查執行緒池狀態 int recheck = ctl.get(); //如果執行緒池處於非執行狀態,則把剛剛加入佇列的任務移除 if (! isRunning(recheck) && remove(command)) //執行拒絕策略 reject(command); //當前沒有工作者執行緒,則新增非核心執行緒 else if (workerCountOf(recheck) == 0) addWorker(null, false); } //如果任務未能加入阻塞佇列,則新增非核心執行緒 corePoolSize => maxPoolSize //如果新增非核心執行緒也失敗,開啟拒絕策略 else if (!addWorker(command, false)) reject(command); //maxPoolSize => maxPoolSize }