《Java並發編程實戰》和《Java並發編程的藝術》 Executor框架小結
1、在線程中如何執行任務
(1)任務執行目標:
在正常負載情況下,服務器應用程序要表現出良好的吞吐率和快速的響應性。在負載過載的情況下,應用程序的性能應該是逐漸減低的,而不是直接失敗。
要實現高吞吐率和快速的響應,就應該選擇清晰的任務邊界和明確的任務執行策略。
(2)任務執行策略有:
1)單線程串行執行任務:缺點:無法提高服務器應用程序的吞吐率和快速響應速度
2)根據任務顯示創建線程:缺點:無限創建線程太消耗資源;線程的創建和消耗開銷高;易造成系統不穩定
3)利用線程池顯示創建線程:
2、任務執行框架-Executor框架
早期Java的線程既是工作單元又是執行機制,而從JDK5開始,使用Runnable和Callable表示工作單元(任務)而由Executor框架負責提供任務的執行機制。
Executor框架封裝了多種不同的任務執行策略,實現了任務的提交與任務的執行的解耦,還提供了對線程生命周期的管理的支持等。
任務的表示:Runnable和Callable或者FutureTask
(1)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;如果終止前超時期滿,則返回 falseboolean 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中的並發工具類