線程池執行任務的過程


線程池是如何工作的呢,借用並發編程藝術一書中的話來描述當一個任務提交給線程池之后,線程池會怎么做?

首先,線程池會判斷核心線程池里的線程(線程總數是30,則coreSize有可能是10)是否都在執行任務。如果沒有比方說當前只有9個線程在工作,則從核心線程池中創建一個新的線程來執行任務。如果當前已經有10個線程在工作了,則進入下一步;

其次,線程池會判斷工作隊列是否已經滿了,如果工作隊列沒有滿,則將新提交的任務存儲在這個工作隊列里,如果工作隊列已經滿了,則進入下一個流程;

最后,線程池判斷全部線程是否都在工作,如果沒有,即30個線程只有25個在工作,則創建一個新的工作線程來執行任務,如果已經有30個線程來執行,沒有任何空閑線程,

則交給飽和策略來處理這個任務(默認的飽和策略為拋異常)。
提交任務之后,首先會嘗試着交給核心線程池中的線程來執行,但是必定核心線程池中的線程數有限,所以必須要由任務隊列來做一個緩存,先將任務放隊列中緩存,然后等待線程去執行,最后,由於任務太多,隊列也滿了,這個時候線程池中剩下的線程就會啟動來幫助核心線程池執行任務。如果還是沒有辦法正常處理新到的任務,則線程池只能將新提交的任務交給飽和策略來處理了。

線程池的創建new ThreadPoolExecutor(corePoolSize,maximumPoolSize,keepAliveTime,milliseconds,

runnableTaskQueue,handler);

其中最后一個參數handler就是飽和策略,java線程池框架提供的4種可策略:

1)AbortPolicy:直接拋出異常

2)CallerRunsPolicy:只用調用者所在線程來運行任務

3)DiscardOldestPolicy:丟棄隊列中最近的一個任務,並執行當前任務。

4)DiscardPolicy:不處理,丟棄掉。

最后我們列舉一個線程池max=5,core=3,任務隊列taskQueue=5;采用飽和策略為1)

則我們看看提交任務給此線程池的執行邏輯如下:

1)首先我們提交第一個任務到線程池,此時核心線程數都還沒有用,所以會啟動核心線程之一來執行任務,記住為了說明這個流程,我們的任務的占用時間都很長,所以短時間內不會結束;

2)接着提交第二個第三個任務到線程池,他們的執行邏輯同第一個任務是一模一樣的,線程池會啟動核心線程池中剩下的兩個線程來執行你新提交的任務。

3)接着又有新的任務提交過來,這個時候線程池發現核心線程池中的線程已經都在工作中,所以會去看任務隊列taskQueue是否滿了,發現並沒有,是空的,所以將這個任務放入任務隊列中等待核心線程池中有空閑線程時自己來取任務執行。

4)接着又提交了4個任務到線程池,他們分別判斷核心線程是否空閑,不空閑,然后判斷任務隊列是否已滿,不滿,則直接將任務放入隊列;

5)接着新的任務又來,則在判斷核心線程池和任務隊列之后,發現任務依然沒有辦法處理,則會判斷是否線程數達到最大,發現沒有,則新啟動線程來執行任務;

6)接着又來一個任務,執行流程同5);

7)再來一個任務,發現核心線程池在忙,任務隊列也滿了,線程池中的全部線程也都在工作,沒有辦法處理他了,所以他找到了飽和策略,因為飽和策略是默認的拋異常,所以線程池會告訴提交任務的線程,已經沒有可以用的線程了。

以上就一個核心線程數是3,總線程數是5,任務隊列長度為5,默認策略采用拋異常的策略的從最開始到最后線程池滿負荷運作的過程


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM