那些年讀過的書《Java並發編程實戰》和《Java並發編程的藝術》三、任務執行框架—Executor框架小結


School《Java並發編程實戰》和《Java並發編程的藝術》           Executor框架小結

1、在線程中如何執行任務

      (1)任務執行目標:

在正常負載情況下,服務器應用程序要表現出良好的吞吐率和快速的響應性。在負載過載的情況下,應用程序的性能應該是逐漸減低的,而不是直接失敗。

要實現高吞吐率和快速的響應,就應該選擇清晰的任務邊界和明確的任務執行策略。

      (2)任務執行策略有:

1)單線程串行執行任務:缺點:無法提高服務器應用程序的吞吐率和快速響應速度

2)根據任務顯示創建線程:缺點:無限創建線程太消耗資源;線程的創建和消耗開銷高;易造成系統不穩定

3)利用線程池顯示創建線程:

2、任務執行框架-Executor框架

            早期Java的線程既是工作單元又是執行機制,而從JDK5開始,使用Runnable和Callable表示工作單元(任務)而由Executor框架負責提供任務的執行機制。

            Executor框架封裝了多種不同的任務執行策略,實現了任務的提交與任務的執行的解耦,還提供了對線程生命周期的管理的支持等。

            任務的表示:Runnable和Callable或者FutureTask

(1)Executor框架類圖和Java隊列類圖

Executor類圖java類圖

 

         (2)線程池

線程池

特點

默認等待隊列

適用場景

ThreadPoolExecutor

newFixedThreadPool

創建固定長度的線程池 返回通用的
ThreadPoolExecutor

無界隊列LinkedBlockingQueue

適用於為了滿足資源管理的需求,而需要限制當前線程數量的場景
適用於負載比較中的服務器

newCachedThreadPool

創建可緩存的線程池,空閑線程會被回收掉,線程池規模不受限制(即線程池大小不限制)返回通用的ThreadPoolExecutor

SynchronousQueue

適用於執行很多短期異步任務的小程序或者負載較輕的服務器

newSingleThreadExecutor

單線程的Executor,創建當個工作者線程來執行任務。
能確保按照任務隊列中的順序執行任務 返回通用的ThreadPoolExecutor

無界隊列LinkedBlockingQueue

適用於需要保證順序執行各個任務,並且在任意時間點不會有多個線程活動的場景

ScheduleThreadPoolExecutor

newScheduledThreadPool

創建固定的線程池並且以延遲或定時的方式來執行任務
返回ScheduledThreadPoolExecutor

無界阻塞隊列DelayQueue

適用於需要多個線程在后台執行周期性任務,同事為了滿足資源管理的需求而現在后台線程的數量的應用場景
適用於需要定時執行任務的場景

newSingleThreadScheduleThreadPool

創建單個線程以順序延遲或者定式的方式執行任務
返回ScheduledThreadPoolExecutor

無界阻塞隊列DelayQueue

適用於需要單個線程順序執行周期性任務的場景

          (3)Executor的生命周期(ExecutorService的接口)

Executor通過擴展ExecutorService接口新增了執行服務的生命周期管理方法,

ExecutorService的生命周期有3種狀態:運行,關閉,已終止

ExecutorService接口方法介紹

方法名稱

作用

返回參數

注意事項

shutdown() 關閉服務,執行平緩的的關閉過程,不再接受新的任務,同時等待所有的任務執行完成(包括已提交但未執行的任務); void  
shutdownNow() 立即關閉,並取消所有任務包括正在執行的和未執行的,然后返回已提交但未執行的任務(不包括那些正在執行被關閉的任務); List<Runnable>  
isShutdown(): 如果此執行程序已關閉,則返回 true boolean  
isTerminated(): 如果關閉后所有任務都已完成,則返回 true。注意,除非首先調用 shutdown 或 shutdownNow,否則 isTerminated 永不為 true。 boolean  
awaitTermination(long timeout,TimeUnit unit) 等待(阻塞)直到關閉或最長等待時間或發生中斷
如果此執行程序終止,則返回 true;如果終止前超時期滿,則返回 false
boolean  

execute(Runnable )

提交一個 Runnable 任務用於執行 void  
submit(Runnable ) 提交一個 Runnable 任務用於執行,並返回一個表示該任務的 Future。該 Future 的 get 方法在成功完成時將會返回給定的結果。

Future<?> 

 

 
submit(Callable<T> ) 提交一個返回值的任務用於執行,返回一個表示任務的未決結果的 Future。該 Future 的 get 方法在成功完成時將會返回該任務的結果。

Future<T>

 

invokeAll(Collection<? extends Callable<T>> tasks,long timeout,TimeUnit unit)

執行給定的任務,當所有任務完成或超時期滿時(無論哪個首先發生),返回保持任務狀態和結果的 Future 列表。返回列表的所有元素的 Future.isDone() 為 true。一旦返回后,即取消尚未完成的任務。
注意,可以正常地或通過拋出異常來終止已完成 任務。如果此操作正在進行時修改了給定的 collection,則此方法的結果是不確定的。
List<Future<T>>
表示任務的 Future 列表,列表順序與給定任務列表的迭代器所生成的順序相同。
     如果操作未超時,則已完成所有任務。如果確實超時了,則某些任務尚未完成。

注意1:該方法會一直阻塞直到所有任務完成或超時。
注意2:如果確實超時了,則某些任務尚未完成。【那么這些尚未完成的任務應該被系統取消】

invokeAll(Collection<? extends Callable<T>> tasks)

執行給定的任務,當所有任務完成時,返回保持任務狀態和結果的 Future 列表。返回列表的所有元素的 Future.isDone() 為 true。
    注意,可以正常地或通過拋出異常來終止已完成 任務。如果正在進行此操作時修改了給定的 collection,則此方法的結果是不確定的。

List<Future<T>>

執行給定的任務,當所有任務完成時,返回保持任務狀態和結果的 Future 列表。返回列表的所有元素的 Future.isDone() 為 true。
    注意,可以正常地或通過拋出異常來終止已完成 任務。如果正在進行此操作時修改了給定的 collection,則此方法的結果是不確定的。

該方法會一直阻塞直到所有任務完成。

 

 

           (3)ScheduledThreadPoolExecutor實現延遲任務與周期任務

             1)比較實現延遲任務與周期任務的兩種方法:

特點

適用情況

Timer a.執行所有定時任務時只創建一個線程,任務執行時間過長時破壞其他定時任務的定時精確性
b.不能處理不捕獲未處理異常,遇到未檢查異常時將終止定時任務,造成“線程泄露”
c.基於絕對時間而不是相對時間的調度機制,任務的執行對系統時鍾變化很敏感
少用
ScheduledThreadPoolExecutor 能夠正確處理執行任務過程中出現的異常
b.基於相對時間的調度
推薦使用

             2)如何構建自己的調度服務

使用DelayQueue為ScheduledThreadPoolExecutor提供調度功能。DelayQueue管理者一組Delayed對象,每個Delayed對象都有一個相應的延遲時間,每個Delayed對象逾期后才能從DelayQueue中執行take操作。

3、如何提高程序的並行性?找出同構並發執行任務

      (1)任務的表示

Runnable:

Callable:可以返回任務執行的結果

      (2)同構任務與異構任務

同構任務:並發執行性能提升少

異構任務:並發執行性能提升多

      (3)Future與CompletionService

Future:作為單個計算句柄

CompletionService:作為一組計算的句柄,CompletionService將Executor和BlockingQueue的功能融合在一起。

CopletionService<ImageData> completionService=new ExecutorCompletService(executor);

completionService.submit(callable);

completionService.take();

      (4)Future.get()與Future.get(TimeOut,TimeUnit)

Future.get() 任務不設時限

Future.get(TimeOut,TimeUnit)為任務設置時限

      (5)Executor.invokeAll(List<Task>,TimeOut,TimeUnit)

將多個任務提交到ExecutorService並獲得一組結果。

4、如何終止線程

 

 

5、Java中的線程池

 

 

6、Java中的並發工具類

 

 

7、並發編程實踐


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM