降低系統資源消耗,通過重用已存在的執行緒,降低執行緒建立和銷毀造成的消耗;
提高系統響應速度,當有任務到達時,通過復用已存在的執行緒,無需等待新執行緒的建立便能立即執行;
方便執行緒併發數的管控。因為執行緒若是無限制的建立,可能會導致記憶體占用過多而產生oom,並且會造成cpu過度切換(cpu切換執行緒是有時間成本的(需要保持當前執行執行緒的現場,並恢復要執行執行緒的現場))。
延時定時執行緒池,可以支援定時任務。
執行緒池流程
判斷核心執行緒池是否已滿,沒滿則建立乙個新的工作執行緒來執行任務。已滿則。
判斷任務佇列是否已滿,沒滿則將新提交的任務新增在工作佇列,已滿則。
判斷整個執行緒池是否已滿,沒滿則建立乙個新的工作執行緒來執行任務,已滿則執行飽和策略。
//構造方法
public
threadpoolexecutor
(int corepoolsize,
int maximumpoolsize,
long
keepalivetime, timeunit unit, blockingqueue
workqueue)
//呼叫
threadpoolexecutor tpe =
newthreadpoolexecutor(2
,4,60
, timeunit.seconds,
newarrayblockingqueue
(4),
executors.
defaultthreadfactory()
,new
threadpoolexecutor.callerrunspolicy()
);
corepoolsize(執行緒池核心執行緒數):當向執行緒池提交乙個任務時,若執行緒池已建立的執行緒數小於corepoolsize,即便此時存在空閒執行緒,也會通過建立乙個新執行緒來執行該任務,直到已建立的執行緒數大於或等於corepoolsize時,(除了利用提交新任務來建立和啟動執行緒(按需構造),也可以通過prestartcorethread() 或 prestartallcorethreads() 方法來提前啟動執行緒池中的基本執行緒。)
maximumpoolsize(執行緒池最大執行緒數):執行緒池所允許的最大執行緒個數。當佇列滿了,且已建立的執行緒數小於maximumpoolsize,則執行緒池會建立新的執行緒來執行任務。另外,對於無界佇列,可忽略該引數。
keepalivetime(執行緒存活保持時間)當執行緒池中線程數大於核心執行緒數時,執行緒的空閒時間如果超過執行緒存活時間,那麼這個執行緒就會被銷毀,直到執行緒池中的執行緒數小於等於核心執行緒數。
workqueue(任務佇列):用於傳輸和儲存等待執行任務的阻塞佇列。
threadfactory(執行緒工廠):用於建立新執行緒。threadfactory建立的執行緒也是採用newthread()方式,threadfactory建立的執行緒名都具有統一的風格:pool-m-thread-n(m為執行緒池的編號,n為執行緒池內的執行緒編號)。
handler(執行緒飽和策略):當執行緒池和佇列都滿了,再加入執行緒會執行此策略。
阻塞佇列:當佇列中元素個數為0時,get()方法阻塞。當佇列已滿時add()方法阻塞。
阻塞佇列可以保證任務佇列中沒有任務時阻塞獲取任務的執行緒,使得執行緒進入wait狀態,釋放cpu資源。當佇列中有任務時才喚醒對應執行緒從佇列中取出訊息進行執行。使得執行緒不會一直占用cpu資源。
盡量使用較小的執行緒池,一般為cpu核心數+1。 因為cpu密集型任務使得cpu使用率很高,若開過多的執行緒數,會造成cpu過度切換。
io密集型任務
可以使用稍大的執行緒池,一般為2*cpu核心數。 io密集型任務cpu使用率並不高,因此可以讓cpu在等待io的時候有其他執行緒去處理別的任務,充分利用cpu時間。
混合型任務
可以將任務分成io密集型和cpu密集型任務,然後分別用不同的執行緒池去處理。 只要分完之後兩個任務的執行時間相差不大,那麼就會比序列執行效率更高。
因為如果劃分之後兩個任務執行時間有資料級的差距,那麼拆分沒有意義。
因為先執行完的任務就要等後執行完的任務,最終的時間仍然取決於後執行完的任務,而且還要加上任務拆分與合併的開銷,得不償失。
blockingqueue知識點可參考blockingqueue的原理及使用方法
常用的幾種blockingqueue:
arrayblockingqueue(int i):
規定大小的blockingqueue,其構造必須指定大小。其所含的物件是fifo順序排序的。
linkedblockingqueue():
或者(int i):大小不固定的blockingqueue,若其構造時指定大小,生成的blockingqueue有大小限制,不指定大小,其大小有integer.max_value來決定。其所含的物件是fifo順序排序的。如果offer()的速度大於pull()的速度,有可能造成記憶體溢位
priorityblockingqueue()或者(int i):
類似於linkedblockingqueue,但是其所含物件的排序不是fifo,而是依據物件的自然順序或者建構函式的comparator決定。
synchronizedqueue():
特殊的blockingqueue,對其的操作必須是放和取交替完成。
cachedthreadpool:
該執行緒池中沒有核心執行緒,非核心執行緒的數量為integer.max_value,就是無限大,當有需要時建立執行緒來執行任務,沒有需要時**執行緒,適用於耗時少,任務量大的情況。使用不當會造成cpu爆滿
secudlethreadpool:
週期性執行任務的執行緒池,按照某種特定的計畫執行執行緒中的任務,有核心執行緒,但也有非核心執行緒,非核心執行緒的大小也為無限大。適用於執行週期性的任務。
singlethreadpool:
只有一條執行緒來執行任務,適用於有順序的任務的應用場景。
fixedthreadpool:
定長的執行緒池,有核心執行緒,核心執行緒的即為最大的執行緒數量,沒有非核心執行緒。使用不當會造成記憶體溢位
execute() 引數 runnable ;submit() 引數 (runnable) 或 (runnable 和 結果 t) 或
(callable)
execute()方法用於提交不需要返回值的任務,所以無法判斷任務是否被執行緒池執行成功與否;
submit()方法用於提交需要返回值的任務。執行緒池會返回乙個 future 型別的物件,通過這個 future
物件可以判斷任務是否執行成功,並且可以通過 future 的get()方法來獲取返回值,get()方法會阻塞當前執行緒直到任務完成,而使用 get(long timeout,timeunit unit)方法則會阻塞當前執行緒一段時間後立即返回,這時候有可能任務沒有執行完。
08 執行緒池
執行緒池的作用是什麼 如果沒有執行緒池,使用者的每乙個請求都會經歷申請資源建立執行緒,執行執行緒,釋放資源銷毀執行緒這個過程,很多時間浪費在建立和銷毀這兩件事情上。如果使用者請求時執行緒已經存在,使用者使用執行緒結束也不用去考慮如何銷毀,由於減少了每個任務呼叫的開銷,它們通常可以在執行大量非同步任務...
執行緒 執行緒池
執行緒池是一種多執行緒處理形式,處理過程中將任務新增到佇列,然後在建立執行緒後執行,主要實現 建立執行緒和管理執行緒,並且給執行緒分配任務。執行緒池中的執行緒是併發執行的。乙個比較簡單的執行緒池至少應包含執行緒池管理器 工作執行緒 任務列隊 任務介面等部分。其中執行緒池管理器的作用是建立 銷毀並管理...
執行緒 執行緒池
乙個簡單執行緒的建立和銷毀如下 與程序程序相比,執行緒是一種輕量級的工具,但是輕量並不代表沒有,它的建立和關閉依然需要花費時間,如果建立和銷毀的時間還大於執行緒本身完成的工作,那就會得不償失,甚至會造成out of memory。即使沒有,大量的執行緒 也會給gc帶來巨大的壓力。為了解決這樣的問題,...