大家好,我是R哥。
最近做 Java 面試輔導,有個學員面試支付寶,遇到一個特別有意思的問題:
如果把執行緒池 corePoolSize 設定為 0,會出現什麼情況?
這個問題一說出來,我都感覺有點***鑽。。
這幾年我創作小程式:Java面試庫,積累了 2700+ 的 Java 面試題,什麼***鑽的面試題沒見過?
像這樣的***鑽面試題確實少見,阿里面試官是真的卷啊。。
大廠學員都覺得會拋異常,事實上真是這樣嗎?
我們來從原始碼來分析下,看看究竟!
先來回顧下執行緒池的工作流程:
1)如果執行緒池中的執行緒小於核心執行緒數 corePoolSize 時,則建立新執行緒直接執行任務。
2)如果執行緒池中的執行緒大於核心執行緒數 corePoolSize 時,則暫時把任務儲存到工作佇列 workQueue 中等待執行。
3)如果工作佇列 workQueue 也滿時:
- 當執行緒數小於最大執行緒池數 maximumPoolSize 時,由建立新執行緒來處理;
- 當執行緒數大於等於最大執行緒池數 maximumPoolSize 時,則執行拒絕策略;
更多參考我的更多 Java 多執行緒系列文章:https://www.javastack.cn/java/thread/
以下是 JDK 21 執行緒池類 ThreadPoolExecutor#execute 方法原始碼:
public void execute(Runnable command) {
// 檢查傳入的任務是否為空,如果為空則丟擲 NullPointerException
if (command == null)
throw new NullPointerException();
// 獲取當前執行緒池的控制狀態
int c = ctl.get();
// 步驟 1: 如果當前執行的執行緒數少於核心執行緒數
if (workerCountOf(c) < corePoolSize) {
// 嘗試新增一個新的工作執行緒來執行提交的任務
// 如果新增成功,則直接返回
if (addWorker(command, true))
return;
// 再次獲取執行緒池的控制狀態,以應對併發變化
c = ctl.get();
}
// 步驟 2
// 步驟 2.1: 如果執行緒池處於執行狀態並且任務能夠成功加入佇列
if (isRunning(c) && workQueue.offer(command)) {
// 再次檢查執行緒池的狀態,確認執行緒池仍然處於執行狀態
int recheck = ctl.get();
// 2.2 如果執行緒池不再執行,並且任務能夠從佇列中移除,則拒絕任務
if (!isRunning(recheck) && remove(command))
reject(command);
// 2.3 如果當前執行緒池沒有執行的執行緒
else if (workerCountOf(recheck) == 0)
// 嘗試新增一個新的非核心工作執行緒(false 表示非核心執行緒)
addWorker(null, false);
}
// 步驟 3
else {
// 3.1 嘗試新增一個新的非核心工作執行緒來執行任務
if (!addWorker(command, false))
// 3.2 如果新增失敗,說明執行緒池已關閉或達到飽和狀態,因此拒絕任務
reject(command);
}
}
我檢查了 JDK 8 和 JDK 17 兩個主版本原始碼,這塊的處理邏輯也是一樣的。
從原始碼可以看到,如果往執行緒池提交任務的時候,當 corePoolSize = 0 時,程式碼正常情況下會執行到步驟2。
以下三步是關鍵步驟:
步驟 2.1:
此時,如果執行緒池處於執行狀態,並且任務能夠成功加入佇列,說明執行緒池不為空,執行緒正常執行任務。
步驟 2.3:
此時,如果當前執行緒池沒有執行的執行緒,則嘗試新增一個新的非核心工作執行緒,即任務會先進入佇列排隊再由執行緒獲取任務執行。
步驟 3.1:
此時,說明佇列滿了無法加入任務,嘗試新增一個新的非核心工作執行緒來執行任務,如果新增失敗,說明執行緒池已關閉或達到飽和狀態,因此拒絕任務。
擴充套件知識點:
這個邏輯在 JDK 6 之前略有不同,在 JDK 6 之前,當 corePoolSize = 0 的時候,先將這個任務放到阻塞佇列中,只有等佇列滿了才建立執行緒來執行,而 JDK 6+ 是直接建立一個非核心執行緒,再放在佇列中來執行,很顯示,JDK 6 這個最佳化動作減小了記憶體溢位的可能性。
光說 JDK 6 和 JDK 8 這兩個版本,對執行緒池的重構就很大,現在主流的版本都是 JDK 8+,這個瞭解一下就好。
這道題可以說是八股文之王了,我工作這麼多年,面試過這麼多人,也沒有見過這道題。
對於阿里這樣的大廠,可能會遇到奇奇怪怪的問題,不會很正常,說說自己的想法,或許不會太減分。但如果你恰好看到了我的公眾號,又學會了這道題,那下次有面試官問起,那就是加分題了,面試官也會對你眼前一亮。
像這樣的面試八股文,我的小程式「Java面試庫」還有許多,比如:
- 為什麼阿里不讓用 Executors 建立執行緒池?
- 執行緒池中的執行緒丟擲了異常,如何處理?
- ......
共 2700+,都是平時我面試別人,或者學員面試覆盤積累下來的真題,不要在網上找亂七八糟的面試題了,浪費時間還容易被誤導。
最後,推薦一波我的「面試輔導訓練營」,有在看機會的,離職的、迷茫的,都可以加入我們的「面試輔導訓練營」,大廠導師 1 v 1 輔導,幫你全面提升面試綜合實力,少走很多彎路,最大化提升職場收益。
版權宣告: 本文系公眾號 "Java技術棧" 原創,轉載、引用本文內容請註明出處,抄襲、洗稿一律投訴侵權,後果自負,並保留追究其法律責任的權利。
更多文章推薦:
1.Spring Boot 3.x 教程,太全了!
2.2,000+ 道 Java面試題及答案整理(2024最新版)
3.免費獲取 IDEA 啟用碼的 7 種方式(2024最新版)
覺得不錯,別忘了隨手點贊+轉發哦!