ThreadPoolExecutor 與常用執行緒池

2021-10-01 11:18:19 字數 3481 閱讀 7562

ps: threadpoolexecutor 原始碼分析請參考 github

為什麼要使用執行緒池

由執行緒池建立、排程、監控和銷毀所有執行緒,控制線程數量,避免出現執行緒洩露,方便管理。

重複利用已建立的執行緒執行任務,不需要持續不斷地重複建立和銷毀執行緒,降低資源消耗。

直接從執行緒池空閒的執行緒中獲取工作執行緒,立即執行任務,不需要每次都建立新的執行緒,從而提高程式的響應速度。

threadpoolexecutor 執行緒池狀態

執行緒池狀態主要有 running, shutdown, stop, tidying, terminated 五種,之間的關係如下圖所示:

running:正常執行狀態,接受新的任務(如果沒有達到拒絕策略的條件)

stop:不接收新任務,也不會執行佇列任務,並且中斷正在執行的任務

tidying:所有任務都已經終止,workercount 為0,當池狀態為tidying時將會執行terminated()方法

terminated:完全終止

threadpoolexecutor 執行緒池主要引數

構造乙個 threadpoolexecutor 執行緒池主要需要以下六個引數

corepoolsize:核心執行緒數,表示通常情況下執行緒池中活躍的執行緒個數;

maximumpoolsize:執行緒池中可容納的最大執行緒數;

workqueue:存放任務的阻塞佇列;

threadfactory:建立新執行緒的執行緒工廠;

handler:執行緒池飽和(任務過多)時的拒絕策略

threadpoolexecutor 執行緒池拒絕策略

此類中預設實現了以下四種拒絕策略(繼承自 rejectedexecutionhandler 類,實現 rejectedexecution 方法):

callerrunspolicy:在呼叫者執行緒(而非執行緒池中的執行緒)中直接執行任務

abortpolicy(預設):直接丟擲 rejectedexecutionexception 異常。程式中需要處理好此異常,不然會影響後續任務的執行。

discardpolicy:直接忽略任務,不執行任何操作。

discardoldestpolicy:丟棄任務佇列中最老的任務,並將對此任務執行 execute。

executors 與常用執行緒池

executors 類,提供了一系列工廠方法用於建立執行緒池,返回的執行緒池都實現了 executorservice 介面,常用以下四種執行緒池(不包括 forkjoinpool):

newcachedthreadpool: 執行緒數量沒有限制(核心執行緒數設定為 0,其實有,最大限制為 integer.max_value),如果執行緒等待時間過長(預設為超過 60 秒),該空閒執行緒會自動終止。

newsinglethreadpool: 只包含乙個執行緒的執行緒池(核心執行緒數和最大執行緒數均為 1),保證任務順序執行。

newscheduledthreadpool: 定長線程池,定時及週期性執行任務。可指定核心執行緒數,最大執行緒數為 interger.max_value。

注意:盡量使用 threadpoolexecutor 而不是 executors 建立執行緒池。

executors 建立的執行緒池物件的弊端如下:

使用案例

比較使用單執行緒和使用 (cpu + 1)個執行緒計算 10 次 1 + 2 + 3 + … + n 的時間消耗(簡單測試),程式如下:

public

class

fixedthreadpoolanalysis

catch

(interruptedexception e)

starttime = system.

nanotime()

; test.

multithread

(n);

endtime = system.

nanotime()

; system.out.

println

("多執行緒計算 10 次 1 + 2 + ... + "

+ n +

" 的時間消耗: "

+(endtime - starttime)

+"ns");

}private

static fixedthreadpoolanalysis test =

newfixedthreadpoolanalysis()

;private

void

singlethread

(int n)

system.out.

println

(thread.

currentthread()

.getname()

+" -> "

+ sum);}

private

void

multithread

(int n)

} fixedthreadpool.

shutdown()

;}class

runimplements

runnable

@override

public

void

run(

) system.out.

println

(thread.

currentthread()

.getname()

+" -> "

+ sum);}

}}

測試所用 cpu 為 8 個,結果如下:

n100

10000

1000000

100000000

1000000000

單執行緒時間消耗(ns)

72500

3321700

23855700

1338836300

12968975200

多執行緒時間消耗(ns)

11469800

16967900

17161400

11226400

19137600

結果顯示,當 n 較小時,由於建立執行緒的時間消耗影響較大,使用多執行緒比使用單執行緒計算同乙個任務的時間消耗更大。當 n 逐漸增大時,使用多執行緒的優勢較明顯。(此處不會出現任務數過多導致 oom,所以為了簡便,使用 executors 建立 fixedthreadpool。)

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個執行緒都需要建立和銷毀,執行緒的建立是需要消耗系統資源...