假設有50個任務,執行緒池設定核心執行緒數為3,等待佇列數設定為5,那麼執行這50個任務時,這3個核心執行緒和2個非核心執行緒就會不停的復用,進行任務的執行。
2.1執行緒池的工作流程
當任務提交之後,執行緒池首先會檢查當前執行緒數,如果當前的執行緒數小於核心執行緒數(corepoolsize),則新建執行緒並執行任務。
當提交的任務不斷增加,建立的執行緒數等於核心執行緒數(corepoolsize),新增的任務會被新增到 workqueue 任務佇列中,等待核心執行緒執行完當前任務後,重新從 workqueue 中獲取任務執行。
當任務數量達到了 workqueue 的最大容量,但是當前執行緒數小於最大執行緒數(maximumpoolsize),執行緒池會在核心執行緒數(corepoolsize)的基礎上繼續創非核心建執行緒來執行任務。
當任務繼續增加,執行緒池的執行緒數達到最大執行緒數(maximumpoolsize),這個時候執行緒池就會採用拒絕策略來拒絕這些任務。
2.2原始碼解析
public
void
execute
(runnable command)
// 核心執行緒已滿,但是任務佇列未滿,新增到佇列中if(
isrunning
(c)&& workqueue.
offer
(command)
)// 核心執行緒池已滿,佇列已滿,嘗試建立乙個非核心新的執行緒
elseif(
!addworker
(command,
false))
// 如果建立新執行緒失敗,說明執行緒池關閉或者執行緒池滿了,拒絕任務
reject
(command)
;}
2.3執行緒復用原始碼解析
final
void
runworker
(worker w)
} completedabruptly =
false;}
finally
}
到這裡已經很明確了,執行緒的復用是通過while迴圈實現的,worker會首先獲取當前的firsttask進行run,然後不停的迴圈從等待佇列中獲取新的任務(task),如果有新任務則直接呼叫task的run方法,不會再去新建乙個執行緒,從而實現復用。
下面附上gettask()的部分原始碼
try
catch
(interruptedexception retry)
執行緒池中的worker通過獲取本身firsttask 或者 通過gettask方法 從等待佇列中不停的迴圈去獲取新的task,呼叫task的run方法執行任務,來實現執行緒的復用。 mysql 執行緒池原始碼 執行緒池原始碼解析
1.前言 我個人覺得理論性的東西可能大家都懂,但是具體的實現細節可能並不是很清楚所以才想記錄一下,加深記憶。2.關鍵原始碼解析 1 ctl private final atomicinteger ctl new atomicinteger ctlof running,0 private static...
執行緒池實現「執行緒復用」的原理?
執行緒復用原理 我們知道執行緒池會使用固定數量或可變數量的執行緒來執行任務,但無論是固定數量或可變數量的執行緒,其執行緒數量都遠遠小於任務數量,面對這種情況執行緒池可以通過執行緒復用讓同乙個執行緒去執行不同的任務,那麼執行緒復用背後的原理是什麼呢?執行緒池建立新執行緒的時機和規則 如流程圖所示,當提...
執行緒池原始碼 執行緒全部關閉了嗎
在前面的文章執行緒池原始碼 執行緒池狀態,我們提到執行緒池的各種狀態,以及執行緒池 shutdown 的流程,但始終有個疑問 shutdown 操作最終能否關閉所有執行緒?為什麼會有這個問題呢?回顧前面提到的 shutdown 流程。檢查是否有終止執行緒池的許可權,會挨個檢查每個執行緒 修改執行緒池...