(1)、定義:
public threadpoolexecutor(int corepoolsize,int maximumpoolsize, long keepalivetime, timeunit unit, blockingqueueworkqueue, rejectedexecutionhandler handler)
(2)、引數說明:
corepoolsize 指的是保留的執行緒池大小。
maximumpoolsize 指的是執行緒池的最大大小。
keepalivetime 指的是空閒執行緒結束的超時時間。
unit 是乙個列舉,表示 keepalivetime 的單位。
workqueue 表示存放任務的佇列。
rejectedexecutionhandler 新增任務失敗後的執行策略,你可以呼叫執行緒池的 setrejectedexecutionhandler() 方法,用自定義的 rejectedexecutionhandler 物件替換現有的策略。
(3)、具體流程如下:
執行緒池剛建立時,裡面沒有乙個執行緒。任務佇列是作為引數傳進來的。不過,就算佇列裡面有任務,執行緒池也不會馬上執行它們。
當呼叫 execute() 方法新增乙個任務時,執行緒池會做如下判斷:
a. 如果正在執行的執行緒數量小於 corepoolsize,那麼馬上建立執行緒執行這個任務;
b. 如果正在執行的執行緒數量大於或等於 corepoolsize,那麼將這個任務放入佇列。
c. 如果這時候佇列滿了,而且正在執行的執行緒數量小於 maximumpoolsize,那麼還是要建立執行緒執行這個任務;
d. 如果佇列滿了,而且正在執行的執行緒數量大於或等於 maximumpoolsize,那麼執行緒池會丟擲異常,告訴呼叫者「我不能再接受任務了」。
當乙個執行緒完成任務時,它會從佇列中取下乙個任務來執行。
另外,當池子的執行緒數大於corepoolsize的時候,多餘的執行緒會等待keepalivetime長的時間,如果無請求可處理就自行銷毀。
(4)、排隊有三種通用策略:
直接提交。工作佇列的預設選項是synchronousqueue,它將任務直接提交給執行緒而不保持它們。在此,如果不存在可用於立即執行任務的執行緒,則試圖把任務加入佇列將失敗,因此會構造乙個新的執行緒。此策略可以避免在處理可能具有內部依賴性的請求集時出現鎖。直接提交通常要求無界 maximumpoolsizes 以避免拒絕新提交的任務。當命令以超過佇列所能處理的平均數連續到達時,此策略允許無界線程具有增長的可能性。
無界佇列。使用無界佇列(例如,不具有預定義容量的linkedblockingqueue)將導致在所有 corepoolsize 執行緒都忙時新任務在佇列中等待。這樣,建立的執行緒就不會超過 corepoolsize。(因此,maximumpoolsize 的值也就無效了。)當每個任務完全獨立於其他任務,即任務執行互不影響時,適合於使用無界佇列;例如,在 web 頁伺服器中。這種排隊可用於處理瞬態突發請求,當命令以超過佇列所能處理的平均數連續到達時,此策略允許無界線程具有增長的可能性。
有界佇列。當使用有限的 maximumpoolsizes 時,有界佇列(如arrayblockingqueue)有助於防止資源耗盡,但是可能較難調整和控制。佇列大小和最大池大小可能需要相互折衷:使用大型佇列和小型池可以最大限度地降低 cpu 使用率、作業系統資源和上下文切換開銷,但是可能導致人工降低吞吐量。如果任務頻繁阻塞(例如,如果它們是 i/o 邊界),則系統可能為超過您許可的更多執行緒安排時間。使用小型佇列通常要求較大的池大小,cpu 使用率較高,但是可能遇到不可接受的排程開銷,這樣也會降低吞吐量。
(5)、新增任務失敗後的4種執行策略
threadpoolexecutor.abortpolicy:表示拒絕任務並丟擲異常
threadpoolexecutor.discardpolicy:表示拒絕任務但不做任何動作
threadpoolexecutor.callerrunspolicy:表示拒絕任務,並在呼叫者的執行緒中直接執行該任務
threadpoolexecutor.discardoldestpolicy:表示先丟棄任務佇列中的第乙個任務,然後把這個任務加進佇列。
eg:使用有界佇列策略。假設佇列大小為 10,corepoolsize 為 3,maximumpoolsize 為 6,那麼當加入 20 個任務時,執行的順序就是這樣的:首先執行任務 1、2、3,然後任務 4-13 被放入佇列。這時候佇列滿了,任務 14、15、16 會被馬上執行,而任務17-20則會新增失敗。最終順序是:1、2、3、14、15、16、4、5、6、7、8、9、10、11、12。
1public
class
threadpoolexe
8public
void
run() catch
(interruptedexception e)
17}
18}
1920
public
void
execute()
26}
2728
public
static
void
main(string args)
輸出結果:
the 1taskthe 3task
the 2task
the 14task
the 15task
the 16task
the 4task
the 6task
the 5task
the 7task
the 8task
the 9task
the 10task
the 13task
the 11task
the 12 task
ThreadPoolExecutor執行緒池原始碼解讀
主要變數 private volatile int corepoolsize private volatile int maximumpoolsize private volatile int poolsize 建構函式 也就是建立類的時候,需要注入引數。public threadpoolexecu...
ThreadPoolExecutor執行緒池引數設定
jdk1.5中引入了強大的concurrent包,其中最常用的莫過了執行緒池的實現threadpoolexecutor,它給我們帶來了極大的方便,但同時,對於該執行緒池不恰當的設定也可能使其效率並不能達到預期的效果,甚至僅相當於或低於單執行緒的效率。threadpoolexecutor類可設定的引數...
ThreadPoolExecutor執行緒池
python中已經有了threading模組,為什麼還需要執行緒池呢,執行緒池又是什麼東西呢?在介紹執行緒同步的訊號量機制的時候,舉得例子是爬蟲的例子,需要控制同時爬取的執行緒數,例子中建立了20個執行緒,而同時只允許3個執行緒在執行,但是20個執行緒都需要建立和銷毀,執行緒的建立是需要消耗系統資源...