好玩的不可思議的ThreadPool執行緒池

2021-10-10 04:08:25 字數 2828 閱讀 3631

jdk1.5為我們新增了兩種實現多執行緒的方式:執行緒池和callable介面,本次我們來玩一下執行緒池。

首先,介紹一下threadpoolexecutor的建構函式及其7個引數的內容:

其次,我們來看一下執行緒池執行任務的流程:

threadpoolexecutor原始碼對execute方法的說明:

其本質就是threadpool執行緒池的執行任務流程,用流程圖標意如下:

在單輪次的多個任務過來時,執行緒池中的執行緒執行任務時完全符合上述規律。

下面我寫了**進行測試,我把核心執行緒數設定為2個,最大可擴充套件執行緒數設定為4個,非核心執行緒數空閒生存時間設定為2s,阻塞佇列設定為3個。

public

class

threadpooldemo);

} timeunit.milliseconds.

sleep

(500);

system.out.

println

("***************==第二輪執行緒***************===");

for(

int i =

0; i <

4; i++))

;}}catch

(interruptedexception e)

finally

}}

測試結果如下:

按照常理來想,那麼第一輪結束後有4個執行緒已經空閒下來了,那麼第二輪任務過來時應該是這些空閒下來的任務直接接收任務,然後執行任務吧。但是測試結果呈現的顯然不是我們預想的。

為了弄清楚其底層的原理,我們先來剖析一下,在第二輪任務來臨時,執行緒池現有4個執行緒處於活躍狀態,阻塞佇列容量為3,現在處於空的狀態。

第二輪有4個任務,但是執行緒只執行了3個任務,有1任務執行了拒絕策略。

明明執行緒池中現在有4個執行緒是處於活躍狀態的,為什麼不將4個任務全部執行,反而要將其中1個任務拒絕呢?

那麼,我又進行了第二次測試。

這次測試,我讓非核心執行緒在空閒2秒後失效(其他**不變),那麼,執行緒池在即將執行第二輪任務時,執行緒池中只剩下核心執行緒(2個),並且阻塞佇列(容量為3)也是空的。

將上述測試**中的

timeunit.milliseconds.

sleep

(500

);

修改為:

timeunit.milliseconds.

sleep

(2500

);

然後執行,測試的結果如下:

本次測試,在第二輪任務來臨時,執行緒池現有2個執行緒處於活躍狀態,阻塞佇列容量為3,而且處於空閒狀態。

這次卻將4個任務全部執行了。

仔細檢視原始碼及其文件說明後,也沒有發現問題。

經過仔細思考,發現執行緒池的執行流程官方文件所寫的是正確的(執行緒池的執行任務流程示意圖表示的流程也是正確的)。因為當多個任務來臨時,執行緒池不是首先判斷是否有空閒的執行緒(execute方法根本就沒有這個流程,這樣的設計完全不符合人的思維習慣),而是直接判定執行緒數是否達到核心執行緒數,如果已達到,則進入阻塞佇列,如果阻塞佇列已滿,再進行判定執行緒數是否已達到最大可擴充套件執行緒數,如果已達到則執行拒絕策略。

詳細分析如下:

在測試1中即將執行第二輪任務時的執行緒池的狀態如下:

執行緒池現有4個執行緒處於活躍狀態,阻塞佇列容量為3,現在處於空的狀態。

當第二輪任務過來後,

1.判定現有執行緒數(目前是4)是否達到核心執行緒數(2),結果是已達到,進行下一步判定;

2.判定阻塞佇列是否已滿,目前任務是4個,阻塞佇列的容量是3個,所以其中有3個任務放入了阻塞佇列,另外1個任務需要進行下一步的判定;

3.判定現有執行緒數(目前是4)是否已達到最大可擴充套件執行緒數(4),結果是已達到,那麼最後1個任務被執行拒絕策略。

在測試2即將執行第二輪任務時執行緒池的狀態如下:

執行緒池現有2個執行緒處於活躍狀態,阻塞佇列容量為3,現在處於空的狀態。

當第二輪任務過來後,

1.判定現有執行緒數(目前是2)是否達到核心執行緒數(2),結果是已達到,進行下一步判定;

2.判定阻塞佇列是否已滿,目前任務是4個,阻塞佇列的容量是3個,所以其中有3個任務放入了阻塞佇列,另外1個任務需要進行下一步的判定;

3.判定現有執行緒數(目前是2)是否已達到最大可擴充套件執行緒數(4),結果是未達到,那麼執行緒池建立新的執行緒,並執行這最後1個任務。

執行緒池的工作流程如下:

1.判定現有執行緒數是否達到核心執行緒數,如果未達到,則建立執行緒並執行任務;

2.如果現有執行緒數已達到核心執行緒數,則判定阻塞佇列是否已滿,未滿則進入阻塞佇列;

3.如果阻塞佇列已滿,則判定現有執行緒數是否已達到最大可擴充套件執行緒數,如果未達到,則建立執行緒並執行任務;

4.如果現有執行緒數已達到最大可擴充套件執行緒數則執行拒絕策略。

官方文件的說明的和原始碼寫的是一致的,經測試也沒有問題,只是執行緒池的這種工作流程不符合人類的思維習慣。

有不可思議的目標 就有不可思議的結果

3月3號 開學 可惜學校的效率不好 要隔上5天才上課 悲劇 最後的半年了 換了新的老師 看上去很有個人魅力 蠻好 尊敬的老師還只有屈指可數的那幾個 失敗。或許是我沒有好好學習,沒有發現 陳昌主 現在的老師絕對算的上乙個,親和力很好,而且很勤奮。寫下這4個月的目標 1 english can read...

不可思議的BUG

莫看江面平如鏡,要看水底萬丈深 記一次由表象引起的不是bug的bug 先上圖 上圖,第一行是實際請求報錯的介面,第二行才是列印出的真正配置的介面位址,由於專案上會根據專案環境,會切換介面位址,方便開發 測試 生產。我的第一反應就是切換位址的邏輯有問題。仔細跟了他寫的 確實在介面請求前,位址是開發位址...

不可思議的縮小vetor

如果vector的空間不夠時,會自動的申請新的空間,空間大小為舊空間的2倍,然後將舊空間的資料拷貝到新空間,最後將舊空間釋放。這種保留額外的記憶體空間已被將來增長的需要,從而防止增加新元素時過於頻繁的重新分配。這也是vector比陣列好的一點。當然有沒有想過,1 如果原有的舊空間為128,現在需要的...