1. 程式人生 > >ThreadPoolExecutor,worker和執行緒工廠之間理解

ThreadPoolExecutor,worker和執行緒工廠之間理解

要說執行緒池就必須說一下核心執行緒數,最大執行緒數和阻塞佇列之間的關係。

其中比較容易讓人誤解的是:corePoolSize,maximumPoolSize,workQueue之間關係。 


1.當執行緒池小於corePoolSize時,新提交任務將建立一個新執行緒執行任務,即使此時執行緒池中存在空閒執行緒。 
2.當執行緒池達到corePoolSize時,新提交任務將被放入workQueue中,等待執行緒池中任務排程執行 
3.當workQueue已滿,且maximumPoolSize>corePoolSize時,新提交任務會建立新執行緒執行任務 
4.當提交任務數超過maximumPoolSize時,新提交任務由RejectedExecutionHandler處理 

5.當執行緒池中超過corePoolSize執行緒,空閒時間達到keepAliveTime時,關閉空閒執行緒 

6.當設定allowCoreThreadTimeOut(true)時,執行緒池中corePoolSize執行緒空閒時間達到keepAliveTime也將關閉

以下是我在網上找到一張可以核心執行緒數,最大執行緒數和阻塞佇列之間關係的圖圖一。


                 圖一

ThreadPoolExecutor中一個執行緒就是一個Worker物件,它與一個執行緒繫結,當Worker執行完畢就是執行緒執行完畢,這個在後面詳細討論執行緒池中執行緒的執行方式。而Worker帶了鎖,根據我後面準備寫的讀寫鎖的例子,發現執行緒池是執行緒安全的。看看圖二的類圖。


 圖二

由圖三可以知道,當提交一個任務時,如果需要建立一個執行緒(何時需要在下一節中探討)時,就呼叫執行緒工廠建立一個執行緒,同時將執行緒繫結到Worker工作佇列中。需要說明的是,Worker佇列構造的時候帶著一個任務Runnable,因此Worker建立時總是繫結著一個待執行任務。換句話說,建立執行緒的前提是有必要建立執行緒(任務數已經超出了執行緒或者強制建立新的執行緒,至於為何強制建立新的執行緒後面章節會具體分析),不會無緣無故建立一堆空閒執行緒等著任務。這是節省資源的一種方式。

一旦執行緒池啟動執行緒後(呼叫執行緒run())方法,那麼執行緒工作佇列Worker就從第1個任務開始執行(這時候發現構造Worker時傳遞一個任務的好處了),一旦第1個任務執行完畢,就從執行緒池的任務佇列中取出下一個任務進行執行。迴圈如此,直到執行緒池被關閉或者任務丟擲了一個RuntimeException。

由此可見,執行緒池的基本原理其實也很簡單,無非預先啟動一些執行緒,執行緒進入死迴圈狀態,每次從任務佇列中獲取一個任務進行執行,直到執行緒池被關閉。如果某個執行緒因為執行某個任務發生異常而終止,那麼重新建立一個新的執行緒而已。如此反覆。

其實,執行緒池原理看起來簡單,但是複雜的是各種策略,例如何時該啟動一個執行緒,何時該終止、掛起、喚醒一個執行緒,任務佇列的阻塞與超時,執行緒池的生命週期以及任務拒絕策略等等



  圖三

特此宣告:以上圖片大部分來自網路