執行緒池原始碼 執行緒全部關閉了嗎

2021-10-03 19:10:11 字數 1746 閱讀 8399

在前面的文章執行緒池原始碼-執行緒池狀態,我們提到執行緒池的各種狀態,以及執行緒池 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...