線程池(知識點) – JAVA編程語言程序開發技術文章

固定線程池
public static ExecutorService newFixdThreadPool(int size);
此方法產生一個具有固定大小的線程池、如果有線程異常中止,將產生新的線程來替代他,參數size用來給出線程池的大小。
public static ExecutorService newSingleThreadExecutor();
此方法創建一個線程池,有點像newFixdThreadPool(1),在同一個時刻隻可以執行一個任務,使用其可以保證多個任務是順序執行的,並且其不可以被重新配置為支持多個線程。如果該線程異常中止,將產生新的線程來替代他。
上述兩個方法返回的都是ExecutorService接口類型的引用。其實,此引用指向的就是線程池對象,可以通過ExecutorService引用調用其execute方法來使用線程池中的線程執行指定的任務,下面給出execute方法詳細參數:
public void execute(Runnable command);
command參數指向實現瞭Runnable接口對象,次對象run方法中的代碼描述瞭要執行的任務。
 
如果希望程序在執行完所有任務後退出,需要調用ExecutorService接口中的shutdown方法來關閉線程池,下面列出瞭兩個關閉線程池的方法:
public void shutdown();
此方法關閉線程池,不再接受新的任務,等待舊結束則關閉所有池中線程。
public void shutdownNow();
此方法無論是否所有任務執行結束,立即關閉線程池,List中為等待執行的任務。
可變尺寸線程池
public static ExecutorService newCacheTheadPool();
此方法將創建一個線程池,線程池的大小不定,當執行任務時先選取重用緩存中已有空閑線程來完成任務,如果沒有空閑線程,則創建新線程,空閑超過60秒的線程將被從線程池中刪除。
延遲線程池
在實際開發中有時需要讓指定在特定的時延之後執行,使用Java中提供的延遲線程池可以很好的滿足這種需求。同樣,延遲線程池也是通過調用Executor類的靜態工廠方法來創建,下面列出瞭創建延遲線程池的兩個靜態方法:
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize);
此方法創建一個線程池,可以以一定的時延執行指定的任務,參數corePoolSize用於指出線程池中的線程數量。
public static ScheduledExecutorService newSingleThreadScheduledExecutor();
此方法用於創建延遲的單線程線程池,也就是說用此方法創建的延遲線程池中隻有一個待命的線程。
ScheduledExecutorService 接口繼承瞭ExecuteService接口,具有ExecuteService接口的所有方法。
ScheduledExecutorService 接口具有其特有的schedule方法來延遲執行指定的任務:
public ScheduledFuture schedule(Runnable runnable,long delay,TimeUnit unit);
此方法調動線程池中的線程,以一定的時延的執行指定的任務,參數runnable表示要執行的任務,delay參數是時延的長度,unit參數表示時延的時間單位。此方法的返回值類型為ScheduledFuture,用來存放有返回結果的任務的結果信息。
自定義參數線程池
如果上述幾種線程池不能滿足我們的需要,我們可以考慮使用ThreadPoolExecutor類來實現自定義的線程池,其內置瞭一個線程隊列(BlockingQueue)。
ThreadPoolExecutor 的繼承關系如下:
Executor->ExecutorService->AbstractExecutorService->ThreadPoolExecutor
核心池大小 (core pool size) 、最大池的大小 (maximum pool size) 、存活時間 (keep-alive time) 共同管理著線程的創建和銷毀。
線程池類為 java.util.concurrent.ThreadPoolExecutor ,常用構造方法為:
Java代碼 
public ThreadPoolExecutor( int corePoolSize,  
 
int maximumPoolSize,  
 
long keepAliveTime,  
 
TimeUnit unit,  
 
BlockingQueue<Runnable> workQueue,  
 
RejectedExecutionHandler handler) {  
 
this (corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,  
 
Executors. defaultThreadFactory (), handler);  
 
}  
 corePoolSize :線程池維護線程的最少數量,哪怕是空閑的。
maximumPoolSize :線程池維護線程的最大數量。
keepAliveTime :線程池維護線程所允許的空閑時間。
unit :線程池維護線程所允許的空閑時間的單位。
workQueue :線程池所使用的緩沖隊列,改緩沖隊列的長度決定瞭能夠緩沖的最大數量。
拒絕任務:拒絕任務是指當線程池裡面的線程數量達到 maximumPoolSize 且 workQueue 隊列已滿的情況下被嘗試添加進來的任務。
handler :線程池對拒絕任務的處理策略。在 ThreadPoolExecutor 裡面定義瞭 4 種 handler 策略,分別是
1. CallerRunsPolicy :這個策略重試添加當前的任務,他會自動重復調用 execute() 方法,直到成功。
2. AbortPolicy :對拒絕任務拋棄處理,並且拋出異常。
3. DiscardPolicy :對拒絕任務直接無聲拋棄,沒有異常信息。
4. DiscardOldestPolicy :對拒絕任務不拋棄,而是拋棄隊列裡面等待最久的一個線程,然後把拒絕任務加到隊列。
 
一個任務通過 execute(Runnable) 方法被添加到線程池,任務就是一個 Runnable 類型的對象,任務的執行方法就是 Runnable 類型對象的 run() 方法。
當一個任務通過 execute(Runnable) 方法欲添加到線程池時,線程池采用的策略如下:
1. 如果此時線程池中的數量小於 corePoolSize ,即使線程池中的線程都處於空閑狀態,也要創建新的線程來處理被添加的任務。
2. 如果此時線程池中的數量等於 corePoolSize ,但是緩沖隊列 workQueue 未滿,那麼任務被放入緩沖隊列。
3. 如果此時線程池中的數量大於 corePoolSize ,緩沖隊列 workQueue 滿,並且線程池中的數量小於 maximumPoolSize ,建新的線程來處理被添加的任務。
4. 如果此時線程池中的數量大於 corePoolSize ,緩沖隊列 workQueue 滿,並且線程池中的數量等於 maximumPoolSize ,那麼通過 handler 所指定的策略來處理此任務。
處理任務的優先級為:
核心線程 corePoolSize 、任務隊列 workQueue 、最大線程 maximumPoolSize ,如果三者都滿瞭,使用 handler 處理被拒絕的任務。當線程池中的線程數量大於 corePoolSize 時,如果某線程空閑時間超過 keepAliveTime ,線程將被終止。這樣,線程池可以動態的調整池中的線程數。
理解瞭上面關於 ThreadPoolExecutord 的介紹,應該就基本能瞭解它的一些使用,不過在 ThreadPoolExocutor 裡面有個關鍵的 Worker 類,所有的線程都要經過 Worker 的包裝。這樣才能夠做到線程可以復用而無需重新創建線程。
同時 Executors 類裡面有 newFixedThreadPool(),newCachedThreadPool() 等幾個方法,實際上也是間接調用瞭 ThreadPoolExocutor ,不過是傳的不同的構造參數。

 

作者“xiehongdong”
 

發佈留言