在前面的文章執行緒池原始碼-執行緒池狀態,我們提到執行緒池的各種狀態,以及執行緒池 shutdown 的流程,但始終有個疑問:shutdown 操作最終能否關閉所有執行緒?
為什麼會有這個問題呢?回顧前面提到的 shutdown 流程。
檢查是否有終止執行緒池的許可權,會挨個檢查每個執行緒
修改執行緒池狀態為 shutdown
終止空閒執行緒,怎麼判斷執行緒是否空閒,通過 trylock() 嘗試獲取它的鎖,如果成功獲取,則證明其為空閒狀態,因為執行任務的時候 worker 會給自己上鎖,是不可重入鎖
呼叫 onshutdown() 方法,此方法預設沒有實現,也是提供給外部的擴充套件介面
後續的終止操作
public
void
shutdown()
finally
// 進行後續的終止操作
tryterminate()
;}
在呼叫 tryterminate() 方法前,空閒執行緒都被 interruptidleworkers() 方法乾掉了,還有一種執行緒活著——正在執行任務的執行緒。因此我的問題就出現了,shutdown 操作最終能否關閉所有執行緒?
把關閉所有執行緒的希望寄託在 tryterminate() 方法上了,我們來看一下**。
final
void
tryterminate()
// 進行最後的 terminate 操作,此處**省略
}}
通過分析原始碼,我們可以想象以下幾種場景。
場景一:
假如此時執行緒狀態是 shutdown,並且任務佇列不為空,則直接停止 terminate 操作,剩下的都是活躍的工作執行緒,此次 shutdown 操作沒有關閉所有執行緒。
場景二:
場景三:
這時 interruptidleworkers(only_one) 中斷操作就發揮作用了,queue.take() 是可以響應外部中斷訊號的。但我仍有疑問——一次只中斷乙個執行緒,那其它同樣阻塞住的執行緒怎麼辦?
我們接著看一下 worker 物件被中斷之後的操作,可以看到它呼叫了 processworkerexit() 方法,並把 completedabruptly 作為引數傳入,這個引數用來標識執行緒是否屬於異常退出,正常情況下 completedabruptly = false。
final
void
runworker
(worker w)
completedabruptly =
false;}
finally
}
來看一下 processworkerexit() 方法,
private
void
processworkerexit
(worker w,
boolean completedabruptly)
finally
// 呼叫 tryterminate 方法,將中斷訊號廣播出去
tryterminate()
;// 後續**省略
}
可以發現它也呼叫了 tryterminate() 方法,問題似乎有答案了,乙個 worker 中斷之後會把中斷訊號廣播出去,如此反覆,直到所有阻塞的 worker 都被中斷,此時 shutdown 操作關閉了所有執行緒。 mysql 執行緒池原始碼 執行緒池原始碼解析
1.前言 我個人覺得理論性的東西可能大家都懂,但是具體的實現細節可能並不是很清楚所以才想記錄一下,加深記憶。2.關鍵原始碼解析 1 ctl private final atomicinteger ctl new atomicinteger ctlof running,0 private static...
執行緒池執行緒復用原理(原始碼詳解)
假設有50個任務,執行緒池設定核心執行緒數為3,等待佇列數設定為5,那麼執行這50個任務時,這3個核心執行緒和2個非核心執行緒就會不停的復用,進行任務的執行。2.1執行緒池的工作流程 當任務提交之後,執行緒池首先會檢查當前執行緒數,如果當前的執行緒數小於核心執行緒數 corepoolsize 則新建...
執行緒池原始碼閱讀(二)
僅大致過了下,有問題的請指出,謝謝。1.8通過乙個樣本場景了解新增任務流程。執行緒池配置 任務 輸出1,睡眠300s,輸出2 執行 新增9個任務至執行緒池 submit 提交任務使用submit 方法,如下 關鍵方法execute public future submit runnable task...