jdk1.5中引入了強大的concurrent包,其中最常用的莫過了執行緒池的實現threadpoolexecutor,它給我們帶來了極大的方便,但同時,對於該執行緒池不恰當的設定也可能使其效率並不能達到預期的效果,甚至僅相當於或低於單執行緒的效率。
threadpoolexecutor類可設定的引數主要有:
核心執行緒數,核心執行緒會一直存活,即使沒有任務需要處理。當執行緒數小於核心執行緒數時,即使現有的執行緒空閒,執行緒池也會優先建立新執行緒來處理任務,而不是直接交給現有的執行緒處理。核心執行緒在allowcorethreadtimeout被設定為true時會超時退出,預設情況下不會退出。
當執行緒數大於或等於核心執行緒,且任務佇列已滿時,執行緒池會建立新的執行緒,直到執行緒數量達到maxpoolsize。如果執行緒數已等於maxpoolsize,且任務佇列已滿,則已超出執行緒池的處理能力,執行緒池會拒絕處理任務而丟擲異常。
當執行緒空閒時間達到keepalivetime,該執行緒會退出,直到執行緒數量等於corepoolsize。如果allowcorethreadtimeout設定為true,則所有執行緒均會退出直到執行緒數量為0。
是否允許核心執行緒空閒退出,預設值為false。
任務佇列容量。從maxpoolsize的描述上可以看出,任務佇列的容量會影響到執行緒的變化,因此任務佇列的長度也需要恰當的設定。執行緒池按以下行為執行任務
當執行緒數小於核心執行緒數時,建立執行緒。
當執行緒數大於等於核心執行緒數,且任務佇列未滿時,將任務放入任務佇列。
當執行緒數大於等於核心執行緒數,且任務佇列已滿
若執行緒數小於最大執行緒數,建立執行緒
若執行緒數等於最大執行緒數,丟擲異常,拒絕任務
系統負載
引數的設定跟系統的負載有直接的關係,下面為系統負載的相關引數:
引數設定
corepoolsize:
每個任務需要tasktime秒處理,則每個執行緒每鈔可處理1/tasktime個任務。系統每秒有tasks個任務需要處理,則需要的執行緒數為:tasks/(1/tasktime),即tasks*tasktime個執行緒數。假設系統每秒任務數為100~1000,每個任務耗時0.1秒,則需要100*0.1至1000*0.1,即10~100個執行緒。那麼corepoolsize應該設定為大於10,具體數字最好根據8020原則,即80%情況下系統每秒任務數,若系統80%的情況下第秒任務數小於200,最多時為1000,則corepoolsize可設定為20。
queuecapacity:
任務佇列的長度要根據核心執行緒數,以及系統對任務響應時間的要求有關。佇列長度可以設定為(corepoolsize/tasktime)*responsetime: (20/0.1)*2=400,即佇列長度可設定為400。
佇列長度設定過大,會導致任務響應時間過長,切忌以下寫法:
linkedblockingqueue queue = new linkedblockingqueue();
這實際上是將佇列長度設定為integer.max_value,將會導致執行緒數量永遠為corepoolsize,再也不會增加,當任務數量陡增時,任務響應時間也將隨之陡增。
maxpoolsize:
當系統負載達到最大值時,核心執行緒數已無法按時處理完所有任務,這時就需要增加執行緒。每秒200個任務需要20個執行緒,那麼當每秒達到1000個任務時,則需要(1000-queuecapacity)*(20/200),即60個執行緒,可將maxpoolsize設定為60。
keepalivetime:
執行緒數量只增加不減少也不行。當負載降低時,可減少執行緒數量,如果乙個執行緒空閒時間達到keepalivetiime,該執行緒就退出。預設情況下執行緒池最少會保持corepoolsize個執行緒。
allowcorethreadtimeout:
預設情況下核心執行緒不會退出,可通過將該引數設定為true,讓核心執行緒也退出。
以上關於執行緒數量的計算並沒有考慮cpu的情況。若結合cpu的情況,比如,當執行緒數量達到50時,cpu達到100%,則將maxpoolsize設定為60也不合適,此時若系統負載長時間維持在每秒1000個任務,則超出執行緒池處理能力,應設法降低每個任務的處理時間(tasktime)。
handler: 執行緒池處理滿倉狀態的策略,預定義四種:
threadpoolexecutor.abortpolicy:處理程式遭到拒絕將丟擲執行時rejectedexecutionexception
threadpoolexecutor.discardpolicy:不能執行的任務將被刪除。
threadpoolexecutor.callerrunspolicy:執行緒呼叫執行該任務的execute本身。新執行緒將會被提交者執行緒執行(就是直接呼叫
run方法,而不是建立乙個新執行緒,呼叫
start
方法),這樣很明顯會減緩提交執行緒的提交速度。此策略提供簡單的反饋控制機制,能夠減緩新任務的提交速度。
threadpoolexecutor.discardoldestpolicy:如果執行程式尚未關閉,則位於工作佇列頭部的任務將被刪除,然後重試執行程式(如果再次失敗,則重複此過程)。
執行緒 執行緒池
執行緒池是一種多執行緒處理形式,處理過程中將任務新增到佇列,然後在建立執行緒後執行,主要實現 建立執行緒和管理執行緒,並且給執行緒分配任務。執行緒池中的執行緒是併發執行的。乙個比較簡單的執行緒池至少應包含執行緒池管理器 工作執行緒 任務列隊 任務介面等部分。其中執行緒池管理器的作用是建立 銷毀並管理...
執行緒 執行緒池
乙個簡單執行緒的建立和銷毀如下 與程序程序相比,執行緒是一種輕量級的工具,但是輕量並不代表沒有,它的建立和關閉依然需要花費時間,如果建立和銷毀的時間還大於執行緒本身完成的工作,那就會得不償失,甚至會造成out of memory。即使沒有,大量的執行緒 也會給gc帶來巨大的壓力。為了解決這樣的問題,...
mysql 執行緒池 c MySQL執行緒池
mysql執行緒池 在麼mysql中,執行緒池指的是用來管理處理mysql客戶端連線任務的執行緒的一種機制。如果把執行緒看做系統資源那麼執行緒池本質上是對系統資源的管理,對應作業系統來說執行緒的建立和銷毀是比較消耗系統資源的,頻繁的建立與銷毀執行緒必然給系統帶來不必要的資源浪費,特別是在高負載的情況...