java.util.concurrent
類 ThreadPoolExecutor
構造函數:
構造方法摘要 | |
---|---|
ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue) 用給定的初始參數和默認的線程工廠及被拒絕的執行處理程序創建新的 ThreadPoolExecutor。 |
|
ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, RejectedExecutionHandler handler) 用給定的初始參數和默認的線程工廠創建新的 ThreadPoolExecutor。 |
|
ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory) 用給定的初始參數和默認被拒絕的執行處理程序創建新的 ThreadPoolExecutor。 |
|
ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler) 用給定的初始參數創建新的 ThreadPoolExecutor。 |
一個 ExecutorService
,它使用可能的幾個池線程之一執行每個提交的任務,通常使用 Executors
工廠方法配置。
線程池可以解決兩個不同問題:由於減少了每個任務調用的開銷,它們通常可以在執行大量異步任務時提供增強的性能,並且還可以提供綁定和管理資源(包括執行任務集時使用的線程)的方法。每個 ThreadPoolExecutor 還維護着一些基本的統計數據,如完成的任務數。
為了便於跨大量上下文使用,此類提供了很多可調整的參數和擴展鈎子 (hook)。但是,強烈建議程序員使用較為方便的 Executors
工廠方法 Executors.newCachedThreadPool()
(無界線程池,可以進行自動線程回收)、Executors.newFixedThreadPool(int)
(固定大小線程池)和 Executors.newSingleThreadExecutor()
(單個后台線程),它們均為大多數使用場景預定義了設置。否則,在手動配置和調整此類時,使用以下指導:
corePoolSize:
線程池的基本大小,即在沒有任務需要執行的時候線程池的大小,並且只有在工作隊列滿了的情況下才會創建超出這個數量的線程。這里需要注意的是:在剛剛創建ThreadPoolExecutor的時候,線程並不會立即啟動,而是要等到有任務提交時才會啟動,除非調用了prestartCoreThread/prestartAllCoreThreads事先啟動核心線程。再考慮到keepAliveTime和allowCoreThreadTimeOut超時參數的影響,所以沒有任務需要執行的時候,線程池的大小不一定是corePoolSize。
maximumPoolSize:
線程池中允許的最大線程數,線程池中的當前線程數目不會超過該值。如果隊列中任務已滿,並且當前線程個數小於maximumPoolSize,那么會創建新的線程來執行任務。這里值得一提的是largestPoolSize,該變量記錄了線程池在整個生命周期中曾經出現的最大線程個數。為什么說是曾經呢?因為線程池創建之后,可以調用setMaximumPoolSize()改變運行的最大線程的數目。
keepAliveTime:
如果一個線程處在空閑狀態的時間超過了該屬性值,就會因為超時而退出。
poolSize:
線程池中當前線程的數量,當該值為0的時候,意味着沒有任何線程,線程池會終止;同一時刻,poolSize不會超過maximumPoolSize。
當新提交一個任務時:
1、如果線程池的當前大小還沒有達到基本大小(poolSize < corePoolSize),那么就新增加一個線程處理新提交的任務;2、如果當前大小已經達到了基本大小,就將新提交的任務提交到阻塞隊列排隊,等候處理workQueue.offer(command);
3、如果隊列容量已達上限,並且當前大小poolSize沒有達到maximumPoolSize,那么就新增線程來處理任務;
4、如果隊列已滿,並且當前線程數目也已經達到上限,那么意味着線程池的處理能力已經達到了極限,此時需要拒絕新增加的任務。至於如何拒絕處理新增的任務,取決於線程池的飽和策略RejectedExecutionHandler。
當 Executor 已經關閉,並且 Executor 將有限邊界用於最大線程和工作隊列容量,且已經飽和時,在方法 execute(java.lang.Runnable)
中提交的新任務將被拒絕。在以上兩種情況下,execute 方法都將調用其 RejectedExecutionHandler
的 RejectedExecutionHandler.rejectedExecution(java.lang.Runnable, java.util.concurrent.ThreadPoolExecutor)
方法。下面提供了四種預定義的處理程序策略:
- 在默認的
ThreadPoolExecutor.AbortPolicy
中,處理程序遭到拒絕將拋出運行時RejectedExecutionException
。 - 在
ThreadPoolExecutor.CallerRunsPolicy
中,線程調用運行該任務的 execute 本身。此策略提供簡單的反饋控制機制,能夠減緩新任務的提交速度。 - 在
ThreadPoolExecutor.DiscardPolicy
中,不能執行的任務將被刪除。 - 在
ThreadPoolExecutor.DiscardOldestPolicy
中,如果執行程序尚未關閉,則位於工作隊列頭部的任務將被刪除,然后重試執行程序(如果再次失敗,則重復此過程)。
也可以自己定義拒絕后的處理策略,可以通過實現 RejectedExecutionHandler 接口來編寫自己的策略。
創建線程:
按需構造 默認情況下,即使核心線程最初只是在新任務到達時才創建和啟動的,也可以使用方法prestartCoreThread()
或
prestartAllCoreThreads()
對其進行動態重寫。如果構造帶有非空隊列的池,則可能希望預先啟動線程。 創建新線程 使用
ThreadFactory
創建新線程。如果沒有另外說明,則在同一個
ThreadGroup
中一律使用
Executors.defaultThreadFactory()
創建線程,並且這些線程具有相同的
NORM_PRIORITY 優先級和非守護進程狀態。通過提供不同的 ThreadFactory,可以改變線程的名稱、線程組、優先級、守護進程狀態,等等。如果從
newThread 返回 null 時
ThreadFactory 未能創建線程,則執行程序將繼續運行,但不能執行任何任務。 保持活動時間
如果池中當前有多於 corePoolSize 的線程,則這些多出的線程在空閑時間超過 keepAliveTime 時將會終止(參見 getKeepAliveTime(java.util.concurrent.TimeUnit)
)。這提供了當池處於非活動狀態時減少資源消耗的方法。如果池后來變得更為活動,則可以創建新的線程。也可以使用方法 setKeepAliveTime(long, java.util.concurrent.TimeUnit)
動態地更改此參數。使用 Long.MAX_VALUE TimeUnit.NANOSECONDS
的值在關閉前有效地從以前的終止狀態禁用空閑線程。默認情況下,保持活動策略只在有多於 corePoolSizeThreads 的線程時應用。但是只要 keepAliveTime 值非 0,allowCoreThreadTimeOut(boolean)
方法也可將此超時策略應用於核心線程。 其中
-
public void allowCoreThreadTimeOut(boolean value)
如果在保持活動時間內沒有任務到達,新任務到達時正在替換(如果需要),則設置控制核心線程是超時還是終止的策略。當為 false(默認值)時,由於沒有傳入任務,核心線程將永遠不會中止。當為 true 時,適用於非核心線程的相同的保持活動策略也同樣適用於核心線程。為了避免連續線程替換,保持活動時間在設置為 true 時必須大於 0。通常應該在主動使用該池前調用此方法。
以上大部分內容來自JavaSE6.0API