天天看點

java并發--Executor 架構

java并發程式設計的藝術 讀書筆記 --------------------------------------- java的線程即使工作單元也是執行機制。工作單元包括Runnable和Callable,執行機制由Executor架構負責。

|||排程模型||| 兩層排程模型。在上層,java應用程式把應用分解為若幹任務,然後使用使用者級的排程器Executor架構來将這些任務映射出成固定數量的線程。在下層,作業系統核心将這些線程映射到硬體處理器上。

|||架構結構||| --任務:實作了Runnable和Callable的任務類。 --執行:核心接口Executor接口及ExecutorService接口。 兩個關鍵實作類:ThreadPoolExecutor和ScheduledThreadPoolExecutor。 --異步計算的結果:Future接口,及其實作類FutureTask。

主線程建立Runnable或者Callable任務,直接ExecutorService執行或者送出給ExecutorService執行(直接建立或者傳回FutureTask對象),主線程調用FutureTask的get方法等待任務執行完成或者調用cancel方法來取消任務的執行。

|||架構成員介紹|||

||ThreadPoolExecutor|| 由四個核心元件構成。 corePool:核心線程池大小 maximumPool:最大線程池大小 BlockingQueue:暫存任務的工作隊列 RejectedExecutionHandler:當ThreadPoolExecutor已經關閉或者飽和(達到maximumPool&&BlockingQueue已經滿),execute方法将要執行的Handler。 通常使用工廠類Executors來建立。 可以建立三種類型的ThreadPoolExecutor。 |FixedThreadPoolExecutor| 建立固定線程數的線程池,被稱為可重用固定線程數的線程池。适用于為了滿足資源管理的需求,而需要限制目前線程數量的應用場景,它适用于負載比較重的伺服器。 new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>()) corePool == maximumPool  && keepAliveTime == 0 && 無界隊列LinkedBlockingQueue不拒絕任務 ---> 固定線程數 BlockingQueue為無界隊列LinkedBlockingQueue ---> 線程數達到corePoolSize之後,任務入隊等待,是以maximumPool無效,并且不會有任務被拒絕

|SingleThreadPool| 建立單個線程的線程池,隻有單個worker線程。适用于需要保證順序的執行各個任務,并且在任意時間點不會有多個線程是活動的應用場景。hr newThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>())

|CachedThreadPool| 根據需要建立大小無界的線程池。适用于執行很多短期異步任務的小程式,或者是負載較輕的伺服器。 new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue<Runnable>()) corePool == 0 && maximumPool == Integer.MAX_VALUE ---> 線程池無界,按需建立 keepAlive == 60s ---> 空閑線程會自動消亡,按需調節線程數量 BlockingQueue為無容量隊列SynchronousQueue ---> 不緩存任務,表明如果任務送出速度超過maximumPool中的線程處理速度,會持續建立新線程,極端情況下會耗盡系統cpu和記憶體資源。 

||ScheduledThreadPoolExecutor|| 主要用于在給定的延遲之後執行任務或者定期執行任務。與Timer類似,但功能更多也更加靈活。Timer對應的是單個背景線程,而ScheduledThreadPoolExecutor可以在構造函數中指定多個對應的背景線程數。 通常使用工廠類Executors來建立。可以建立兩種類型的ScheduledThreadPoolExecutor |ScheduledThreadPoolExecutor| 建立固定線程數的線程池。适用于需要多個背景線程執行周期任務,同時為了滿足資源管理的需求而需要限制背景線程數量的應用場景。 BlockingQueue為無界隊列DelayQueue(封裝了一個PriorityQueue) --->maximumPool參數無意義 待排程的任務ScheduledFutureTask由三個成員變量: -time:表示這個任務将要被執行的具體時間 -sequenceNum:表示這個任務被添加到ScheduledThreadPoolExecutor的序列号 -period:任務的排程周期 DelayQueue的排序規則:time優先,time相同sequenceNum優先。是以,時間早的任務先執行,在此基礎上先送出的任務先執行。

|SingleThreadScheduledExecutor| 建立單個線程的線程池。适用于需要單個背景線程執行周期任務,同時需要保證順序的執行各個任務的應用場景。

||Future|| Future接口及其實作類FutureTask用來表示異步計算的結果。當把Runnable/Callable對象submit給ThreadPoolExecutor/ScheduledThreadPoolExecutor時,會傳回一個Future/FutureTask對象。 FutureTask除了實作了Future接口之外還實作了Runnable接口。是以FutureTask可以交給Executor執行,也可以由調用線程直接執行(FutureTask.run())。根據執行的時機,FutureTask由三種狀态。 -未啟動:建立了FutureTask但未執行run方法。 調用get方法,調用線程将阻塞 調用cancel方法,則該任務将永遠不會被執行 -已啟動:run執行過程中 調用get方法,調用線程将阻塞 調用cancle(true)方法,将以中斷執行此任務線程的方式來試圖停止任務 調用cancle(false)方法,不會對正在執行的任務産生影響,該任務将執行完畢 -已完成:run正常結束/cancel/異常抛出 調用get方法,調用線程立即傳回結果或抛出異常 調用cancel方法,将傳回false

||Runnable/Callable|| 其實作類可以被Executor執行。差別是Runnable不會傳回結果,Callable可以傳回結果。除了可以自己建立Callable之外,可以直接用工廠類Executors來将一個Runnable包裝稱為Callable。

繼續閱讀