jdk執行緒池總類以及執行緒池的核心引數簡述
JDK自帶執行緒池總類:
1、newFixedThreadPool建立一個指定工作執行緒數量的執行緒池。每當提交一個任務就建立一個工作執行緒,如果工作執行緒數量達到執行緒池初始的最大數,則將提交的任務存入到池佇列中。
2、newCachedThreadPool建立一個可快取的執行緒池。這種型別的執行緒池特點是:
1).工作執行緒的建立數量幾乎沒有限制(其實也有限制的,數目為Interger.MAX_VALUE),這樣可靈活的往執行緒池中新增執行緒。
2).如果長時間沒有往執行緒池中提交任務,即如果工作執行緒空閒了指定的時間(預設為1分鐘),則該工作執行緒將自動終止。終止後,如果你又提交了新的任務,則執行緒池重新建立一個工作執行緒。
3、newSingleThreadExecutor建立一個單執行緒化的Executor,即只建立唯一的工作者執行緒來執行任務,如果這個執行緒異常結束,會有另一個取代它,保證順序執行(我覺得這點是它的特色)。單工作執行緒最大的特點是可保證順序地執行各個任務,並且在任意給定的時間不會有多個執行緒是活動的。
4、newScheduleThreadPool建立一個定長的執行緒池,而且支援定時的以及週期性的任務執行,類似於Timer。(這種執行緒池原理暫還沒完全
瞭解透徹)
總結:
一.FixedThreadPool是一個典型且優秀的執行緒池,它具有執行緒池提高程式效率和節省建立執行緒時所耗的開銷的優點。但是,線上程池空閒時,即執行緒池中沒有可執行任務時,它不會釋放工作執行緒,還會佔用一定的系統資源。
二.CachedThreadPool的特點就是線上程池空閒時,即執行緒池中沒有可執行任務時,它會釋放工作執行緒,從而釋放工作執行緒所佔用的資源。但是,但當出現新任務時,又要建立一新的工作執行緒,又要一定的系統開銷。並且,在使用CachedThreadPool時,一定要注意控制任務的數量,否則,由於大量執行緒同時執行,很有會造成系統癱瘓。
執行緒池的原理開始初始化若干執行緒處於休眠狀態等待呼叫,不用頻繁建立銷燬減少cpu開支,提升部分效能。
執行緒池的引數配置詳解
1、ThreadPoolExecutor的重要引數
corePoolSize:核心執行緒數
核心執行緒會一直存活,及時沒有任務需要執行
當執行緒數小於核心執行緒數時,即使有執行緒空閒,執行緒池也會優先建立新執行緒處理
設定allowCoreThreadTimeout=true(預設false)時,核心執行緒會超時關閉
queueCapacity:任務佇列容量(阻塞佇列)
當核心執行緒數達到最大時,新任務會放在佇列中排隊等待執行
maxPoolSize:最大執行緒數
當執行緒數>=corePoolSize,且任務佇列已滿時。執行緒池會建立新執行緒來處理任務
當執行緒數=maxPoolSize,且任務佇列已滿時,執行緒池會拒絕處理任務而丟擲異常
keepAliveTime:執行緒空閒時間
當執行緒空閒時間達到keepAliveTime時,執行緒會退出,直到執行緒數量=corePoolSize
如果allowCoreThreadTimeout=true,則會直到執行緒數量=0
allowCoreThreadTimeout:允許核心執行緒超時
rejectedExecutionHandler:任務拒絕處理器
兩種情況會拒絕處理任務:
當執行緒數已經達到maxPoolSize,切佇列已滿,會拒絕新任務
當執行緒池被呼叫shutdown()後,會等待執行緒池裡的任務執行完畢,再shutdown。如果在呼叫shutdown()和執行緒池真正shutdown之間提交任務,會拒絕新任務
執行緒池會呼叫rejectedExecutionHandler來處理這個任務。如果沒有設定預設是AbortPolicy,會丟擲異常
ThreadPoolExecutor類有幾個內部實現類來處理這類情況:
AbortPolicy 丟棄任務,拋執行時異常
CallerRunsPolicy 執行任務
DiscardPolicy 忽視,什麼都不會發生
DiscardOldestPolicy 從佇列中踢出最先進入佇列(最後一個執行)的任務
實現RejectedExecutionHandler介面,可自定義處理器
2、ThreadPoolExecutor執行順序:
執行緒池按以下行為執行任務
當執行緒數小於核心執行緒數時,建立執行緒。
當執行緒數大於等於核心執行緒數,且任務佇列未滿時,將任務放入任務佇列。
當執行緒數大於等於核心執行緒數,且任務佇列已滿
若執行緒數小於最大執行緒數,建立執行緒
若執行緒數等於最大執行緒數,丟擲異常,拒絕任務
3、如何設定引數
預設值
corePoolSize=1
queueCapacity=Integer.MAX_VALUE
maxPoolSize=Integer.MAX_VALUE
keepAliveTime=60s
allowCoreThreadTimeout=false
rejectedExecutionHandler=AbortPolicy()
如何來設定
需要根據幾個值來決定
tasks :每秒的任務數,假設為500~1000
taskcost:每個任務花費時間,假設為0.1s
responsetime:系統允許容忍的最大響應時間,假設為1s
做幾個計算
corePoolSize = 每秒需要多少個執行緒處理?
threadcount = tasks/(1/taskcost) =tasks*taskcout = (500~1000)*0.1 = 50~100 個執行緒。corePoolSize設定應該大於50
根據8020原則,如果80%的每秒任務數小於800,那麼corePoolSize設定為80即可
queueCapacity = (coreSizePool/taskcost)*responsetime
計算可得 queueCapacity = 80/0.1*1 = 80。意思是佇列裡的執行緒可以等待1s,超過了的需要新開執行緒來執行
切記不能設定為Integer.MAX_VALUE,這樣佇列會很大,執行緒數只會保持在corePoolSize大小,當任務陡增時,不能新開執行緒來執行,響應時間會隨之陡增。
maxPoolSize = (max(tasks)- queueCapacity)/(1/taskcost)
計算可得 maxPoolSize = (1000-80)/10 = 92
(最大任務數-佇列容量)/每個執行緒每秒處理能力 = 最大執行緒數
rejectedExecutionHandler:根據具體情況來決定,任務不重要可丟棄,任務重要則要利用一些緩衝機制來處理
keepAliveTime和allowCoreThreadTimeout採用預設通常能滿足
以上都是理想值,實際情況下要根據機器效能來決定。如果在未達到最大執行緒數的情況機器cpu load已經滿了,則需要通過升級硬體(呵呵)和優化程式碼,降低taskcost來處理。
如有披露或問題歡迎留言或者入群探討