摘要: Eexecutor作為靈活且強大的異步執(zhí)行框架,其支持多種不同類型的任務執(zhí)行策略,提供了一種標準的方法將任務的提交過程和執(zhí)行過程解耦開發(fā),基于生產(chǎn)者-消費者模式,其提交任務的線程相當于生產(chǎn)者,執(zhí)行任務的線程相當于消費者,并用Runnable來表示任務,Executor的實現(xiàn)還提供了對生命周期的支持,以及統(tǒng)計信息收集,應用程序管理機制和性能監(jiān)視等機制。
1.Exexctor簡介
Executor的UML圖:(常用的幾個接口和子類)
Executor:一個接口,其定義了一個接收Runnable對象的方法executor,其方法簽名為executor(Runnable command),
ExecutorService:是一個比Executor使用更廣泛的子類接口,其提供了生命周期管理的方法,以及可跟蹤一個或多個異步任務執(zhí)行狀況返回Future的方法
AbstractExecutorService:ExecutorService執(zhí)行方法的默認實現(xiàn)
ScheduledExecutorService:一個可定時調(diào)度任務的接口
ScheduledThreadPoolExecutor:ScheduledExecutorService的實現(xiàn),一個可定時調(diào)度任務的線程池
ThreadPoolExecutor:線程池,可以通過調(diào)用Executors以下靜態(tài)工廠方法來創(chuàng)建線程池并返回一個ExecutorService對象:
2.ThreadPoolExecutor構(gòu)造函數(shù)的各個參數(shù)說明
ThreadPoolExecutor方法簽名:
參數(shù)說明:
corePoolSize:核心線程數(shù),如果運行的線程少于corePoolSize,則創(chuàng)建新線程來執(zhí)行新任務,即使線程池中的其他線程是空閑的
maximumPoolSize:最大線程數(shù),可允許創(chuàng)建的線程數(shù),corePoolSize和maximumPoolSize設置的邊界自動調(diào)整池大?。?/div>
corePoolSize <運行的線程數(shù)< maximumPoolSize:僅當隊列滿時才創(chuàng)建新線程
corePoolSize=運行的線程數(shù)= maximumPoolSize:創(chuàng)建固定大小的線程池
keepAliveTime:如果線程數(shù)多于corePoolSize,則這些多余的線程的空閑時間超過keepAliveTime時將被終止
unit:keepAliveTime參數(shù)的時間單位
workQueue:保存任務的阻塞隊列,與線程池的大小有關(guān):
當運行的線程數(shù)少于corePoolSize時,在有新任務時直接創(chuàng)建新線程來執(zhí)行任務而無需再進隊列
當運行的線程數(shù)等于或多于corePoolSize,在有新任務添加時則選加入隊列,不直接創(chuàng)建線程
當隊列滿時,在有新任務時就創(chuàng)建新線程
threadFactory:使用ThreadFactory創(chuàng)建新線程,默認使用defaultThreadFactory創(chuàng)建線程
handle:定義處理被拒絕任務的策略,默認使用ThreadPoolExecutor.AbortPolicy,任務被拒絕時將拋出RejectExecutorException
3.Executors:提供了一系列靜態(tài)工廠方法用于創(chuàng)建各種線程池
newFixedThreadPool:創(chuàng)建可重用且固定線程數(shù)的線程池,如果線程池中的所有線程都處于活動狀態(tài),此時再提交任務就在隊列中等待,直到有可用線程;如果線程池中的某個線程由于異常而結(jié)束時,線程池就會再補充一條新線程。
方法簽名:
public static ExecutorService newFixedThreadPool(int nThreads) { return new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS, //使用一個基于FIFO排序的阻塞隊列,在所有corePoolSize線程都忙時新任務將在隊列中等待 new LinkedBlockingQueue<Runnable>()); } newSingleThreadExecutor:創(chuàng)建一個單線程的Executor,如果該線程因為異常而結(jié)束就新建一條線程來繼續(xù)執(zhí)行后續(xù)的任務
方法簽名:
newScheduledThreadPool:創(chuàng)建一個可延遲執(zhí)行或定期執(zhí)行的線程池
方法簽名:
例1:(使用newScheduledThreadPool來模擬心跳機制)
1 public class HeartBeat { 2 public static void main(String[] args) { 3 ScheduledExecutorService executor = Executors.newScheduledThreadPool(5); 4 Runnable task = new Runnable() { 5 public void run() { 6 System.out.println("HeartBeat........................."); 7 } 8 }; 9 executor.scheduleAtFixedRate(task,5,3, TimeUnit.SECONDS); //5秒后第一次執(zhí)行,之后每隔3秒執(zhí)行一次 10 } 11 } 輸出:
HeartBeat....................... //5秒后第一次輸出 HeartBeat....................... //每隔3秒輸出一個 newCachedThreadPool:創(chuàng)建可緩存的線程池,如果線程池中的線程在60秒未被使用就將被移除,在執(zhí)行新的任務時,當線程池中有之前創(chuàng)建的可用線程就重 用可用線程,否則就新建一條線程
方法簽名:
public static ExecutorService newCachedThreadPool() { return new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, //使用同步隊列,將任務直接提交給線程 new SynchronousQueue<Runnable>()); } 例2:
輸出:(為每個任務新建一條線程,共創(chuàng)建了3條線程)
線程名字: pool-1-thread-1 任務名為: 1 線程名字: pool-1-thread-2 任務名為: 2 線程名字: pool-1-thread-3 任務名為: 3 去掉第6行的注釋其輸出如下:(始終重復利用一條線程,因為newCachedThreadPool能重用可用線程)
線程名字: pool-1-thread-1 任務名為: 1 線程名字: pool-1-thread-1 任務名為: 2 線程名字: pool-1-thread-1 任務名為: 3 通過使用Executor可以很輕易的實現(xiàn)各種調(diào)優(yōu) 管理 監(jiān)視 記錄日志和錯誤報告等待。
4.Executor的生命周期
ExecutorService提供了管理Eecutor生命周期的方法,ExecutorService的生命周期包括了:運行 關(guān)閉和終止三種狀態(tài)。
ExecutorService在初始化創(chuàng)建時處于運行狀態(tài)。
shutdown方法等待提交的任務執(zhí)行完成并不再接受新任務,在完成全部提交的任務后關(guān)閉
shutdownNow方法將強制終止所有運行中的任務并不再允許提交新任務
可以將一個Runnable(如例2)或Callable(如例3)提交給ExecutorService的submit方法執(zhí)行,最終返回一上Futire用來獲得任務的執(zhí)行結(jié)果或取消任務
例3:(任務執(zhí)行完成后并返回執(zhí)行結(jié)果)
輸出:
任務的執(zhí)行結(jié)果:MOBIN ExecutorCompletionService:實現(xiàn)了CompletionService,將執(zhí)行完成的任務放到阻塞隊列中,通過take或poll方法來獲得執(zhí)行結(jié)果
例4:(啟動10條線程,誰先執(zhí)行完成就返回誰)
輸出結(jié)果可能每次都不同(在1到10之間)
3 通過Executor來設計應用程序可以簡化開發(fā)過程,提高開發(fā)效率,并有助于實現(xiàn)并發(fā),在開發(fā)中如果需要創(chuàng)建線程可優(yōu)先考慮使用Executor
|
|