日韩成人免费在线_国产成人一二_精品国产免费人成电影在线观..._日本一区二区三区久久久久久久久不

當前位置:首頁 > 科技  > 軟件

ExecutorCompletionService詳解,你學會了嗎?

來源: 責編: 時間:2024-01-02 17:28:18 213觀看
導讀本文將深入講解 ExecutorCompletionService 的使用以及源碼解析。ExecutorCompletionService適用場景ExecutorCompletionService在以下場景中特別有用:并行任務處理:當需要同時執行多個任務,并按照完成的順序獲取它們的

本文將深入講解 ExecutorCompletionService 的使用以及源碼解析。poB28資訊網——每日最新資訊28at.com

ExecutorCompletionService適用場景

ExecutorCompletionService在以下場景中特別有用:poB28資訊網——每日最新資訊28at.com

  • 并行任務處理:當需要同時執行多個任務,并按照完成的順序獲取它們的結果時,可以使用ExecutorCompletionService來簡化任務提交和結果獲取的流程。
  • 高性能計算:在需要進行大規模計算或復雜計算的場景中,可以將任務拆分成多個子任務,并使用ExecutorCompletionService來管理和獲取子任務的結果。

假設現在有一批需要進行計算的任務,為了提高整批任務的執行效率,我們可以使用線程池來異步計算這些任務。通過向線程池中不斷提交任務并保留與每個任務關聯的Future對象。最后,我們可以遍歷這些Future對象,并通過調用 get() 方法獲取每個任務的計算結果。poB28資訊網——每日最新資訊28at.com

Future的不足

Future 沒有辦法回調,只能手動去調用,當通過 get() 方法獲取線程的返回值時,會導致阻塞,也就是和當前這個 Future 關聯的計算任務執行完成的時候才返回結果,新任務必須等待已完成任務的結果才能繼續進行處理。poB28資訊網——每日最新資訊28at.com

這樣會浪費很多時間,因為我們不知道哪個線程先執行完了,只能挨個去獲取結果,這樣已經完成的線程會因為前面未完成的線程的耗時而無法提前進行匯總,最好是誰先執行完成,誰先返回。poB28資訊網——每日最新資訊28at.com

而 ExecutorCompletionService 可以實現這樣的效果,節省獲取完成結果的時間,它的內部有一個先進先出的阻塞隊列,用于保存已經執行完成的 Future,通過調用它的 take() 方法或 poll() 方法可以獲取到一個已經執行完成的 Future,進而通過調用 Future 接口實現類的 get() 方法獲取最終的結果。poB28資訊網——每日最新資訊28at.com

CompletionService的目標是任務誰先完成誰先獲取,即結果按照完成先后順序排序poB28資訊網——每日最新資訊28at.com

ExecutorCompletionService使用

ExecutorCompletionService 提供了一種方便的方式來處理一組異步任務,并按照完成的順序獲取它們的結果。它內部使用了Executor框架來執行任務,并且內部管理著一個已完成任務的阻塞隊列,在結果獲取上提供了更加靈活和高效的機制。poB28資訊網——每日最新資訊28at.com

下面是一個簡單的例子來演示ExecutorCompletionService的基本使用:poB28資訊網——每日最新資訊28at.com

public class ExecutorCompletionServiceExample {    public static void main(String[] args) throws InterruptedException, ExecutionException {        ExecutorService executor = Executors.newFixedThreadPool(5);        CompletionService<String> completionService = new ExecutorCompletionService<>(executor);        // 提交任務        for (int i = 0; i < 10; i++) {            final int taskId = i;            completionService.submit(() -> {                double sleepTime = Math.random() * 1000;                Thread.sleep((long) sleepTime); // 模擬耗時操作                return "Task " + taskId + " completed,cost time: " + sleepTime;            });        }        // 獲取結果        for (int i = 0; i < 10; i++) {            Future<String> future = completionService.take();            String result = future.get();            System.out.println(result);        }        executor.shutdown();    }}

輸出:poB28資訊網——每日最新資訊28at.com

Task 2 completed,cost time: 170.01927312611775Task 3 completed,cost time: 460.9622858036789Task 1 completed,cost time: 563.24738180643Task 0 completed,cost time: 595.938819219159Task 5 completed,cost time: 480.4473056068137Task 4 completed,cost time: 748.2343208613524Task 6 completed,cost time: 370.4679098376097Task 7 completed,cost time: 270.45945981324905Task 9 completed,cost time: 336.5536570760892Task 8 completed,cost time: 577.5774464801026

在上述代碼中,我們創建了一個固定大小的線程池,并使用 ExecutorCompletionService 來提交和獲取任務的結果。通過調用completionService.submit()方法來提交任務,并隨機指定睡眠時間,來模擬任務執行的耗時,然后通過completionService.take()方法來獲取已完成的任務結果。poB28資訊網——每日最新資訊28at.com

可以看到是按照任務的執行耗時順序去獲取結果的。poB28資訊網——每日最新資訊28at.com

ExecutorCompletionService原理解析

ExecutorCompletionService 提供了兩個構造函數,一個可以指定阻塞隊列,另一個使用內部默認的阻塞隊列,兩個構造函數都需要傳進線程池參數。poB28資訊網——每日最新資訊28at.com

圖片圖片poB28資訊網——每日最新資訊28at.com

提供了三個獲取方法,可以看到都是從隊列中獲取。poB28資訊網——每日最新資訊28at.com

  • take()/poll() 方法的工作都委托給內部的已完成任務隊列 completionQueue。
  • 如果隊列中有已完成的任務, take() 方法就返回任務的結果,否則阻塞等待任務完成。
  • poll() 與 take() 方法不同,poll() 有兩個版本:

無參的 poll() 方法:如果完成隊列中有數據就返回,否則返回null。poB28資訊網——每日最新資訊28at.com

有參數的 poll() 方法:如果完成隊列中有數據就直接返回,否則等待指定的時間,到時間后如果還是沒有數據就返回null。poB28資訊網——每日最新資訊28at.com

圖片圖片poB28資訊網——每日最新資訊28at.com

兩個提交任務方法,可以看到 submit() 方法最終會委托給內部的 executor 去執行任務,提交任務的時候會將任務封裝成 QueueingFuture 對象。poB28資訊網——每日最新資訊28at.com

圖片圖片poB28資訊網——每日最新資訊28at.com

ExecutorCompletionService內部維護了 QueueingFuture 類,QueueingFuture 繼承了 FutureTask,并重寫了 done() 方法,poB28資訊網——每日最新資訊28at.com

可以看到 done() 方法在任務完成的時候會將結果存進 已完成任務隊列 completionQueue 中。poB28資訊網——每日最新資訊28at.com

圖片圖片poB28資訊網——每日最新資訊28at.com

Futuretask 的 done() 方法是用來標記一個任務已經完成的方法。當一個 Futuretask 中的任務完成后,就會調用 done() 方法通知。poB28資訊網——每日最新資訊28at.com

圖片圖片poB28資訊網——每日最新資訊28at.com

默認是空方法,不會執行任何動作。poB28資訊網——每日最新資訊28at.com

圖片圖片poB28資訊網——每日最新資訊28at.com

執行流程

當我們使用ExecutorCompletionService類時,它能夠按照任務完成的順序獲取它們的結果,這是因為ExecutorCompletionService類內部結合了QueueingFuture類和done()方法的機制。以下是源碼流程步驟解釋:poB28資訊網——每日最新資訊28at.com

  1. 提交任務:

我們通過submit方法將任務提交給ExecutorCompletionService。在提交任務時,ExecutorCompletionService會使用自定義的QueueingFuture類來包裝任務,并將其交給底層線程池執行。poB28資訊網——每日最新資訊28at.com

  1. QueueingFuture類:

QueueingFuture類是ExecutorCompletionService的內部類,繼承自FutureTask。它的構造方法接收一個Callable對象作為參數。poB28資訊網——每日最新資訊28at.com

在QueueingFuture類中,它重寫了done()方法。done()方法會在任務執行完成后被調用。poB28資訊網——每日最新資訊28at.com

  1. 任務執行完成時的處理:poB28資訊網——每日最新資訊28at.com

當任務執行完成后,在底層線程池的Worker線程中,會調用QueueingFuture的done()方法。poB28資訊網——每日最新資訊28at.com

在done()方法中,QueueingFuture會首先調用父類FutureTask的done()方法,以觸發對計算結果的獲取。然后,它會將任務的結果存儲到一個內部的BlockingQueue隊列中(即completionQueue)。poB28資訊網——每日最新資訊28at.com

  1. 獲取任務結果:poB28資訊網——每日最新資訊28at.com

當我們調用take方法獲取任務結果時,它會從completionQueue隊列中取出已完成的任務結果,并返回該結果。如果隊列為空,則會阻塞等待,直到有任務完成并返回結果。poB28資訊網——每日最新資訊28at.com

take方法內部會調用QueueingFuture的get()方法,從而觸發對應任務的計算結果的獲取。poB28資訊網——每日最新資訊28at.com

  1. 保證按順序獲取結果:poB28資訊網——每日最新資訊28at.com

由于completionQueue是一個阻塞隊列,并且在done()方法中將任務結果按照完成的順序放入隊列中,因此我們可以通過按順序獲取隊列中的任務結果,來保證按照任務完成的順序獲取它們的結果。poB28資訊網——每日最新資訊28at.com

通過以上源碼流程步驟,ExecutorCompletionService類能夠按照任務完成的順序獲取結果。它利用QueueingFuture類包裝任務并存儲結果到阻塞隊列中,在任務執行完成后,按照完成的順序將結果放入隊列,從而實現了按順序獲取結果的功能。poB28資訊網——每日最新資訊28at.com

注意事項

在使用ExecutorCompletionService時,需要注意以下事項:poB28資訊網——每日最新資訊28at.com

  • 合理選擇線程池大小:根據任務的數量和復雜性,合理選擇線程池的大小,以充分利用系統資源并避免資源浪費。
  • 及時處理異常:在任務執行過程中,如果發生異常,需要及時處理和記錄異常信息,以保證程序的穩定性和可靠性。
  • 使用Future對象進行任務取消和超時控制:通過使用Future對象的cancel方法,可以取消正在執行的任務。同時,可以通過調整 poll 方法的參數來設置超時時間,避免長時間等待任務結果而導致阻塞。

總結

ExecutorCompletionService是一個強大且靈活的工具類,能夠簡化異步任務的處理和結果獲取過程。通過使用ExecutorCompletionService,我們可以更加高效地處理一組異步任務,并按照完成的順序獲取它們的結果。poB28資訊網——每日最新資訊28at.com

本文介紹了ExecutorCompletionService的基本使用方法,并對其源碼進行了解析。希望通過這篇博客能夠幫助讀者更好地理解和應用ExecutorCompletionService。poB28資訊網——每日最新資訊28at.com

本文鏈接:http://www.www897cc.com/showinfo-26-56415-0.htmlExecutorCompletionService詳解,你學會了嗎?

聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。郵件:2376512515@qq.com

上一篇: 利用Go傳統RPC和gRPC框架分別實現一個RPC服務端

下一篇: 兩種方法實現 Http Request Body 多次讀取

標簽:
  • 熱門焦點
Top 主站蜘蛛池模板: 宾川县| 金门县| 霍邱县| 黄山市| 嘉禾县| 佛学| 通榆县| 读书| 鄂托克旗| 华池县| 凭祥市| 厦门市| 共和县| 临高县| 岑巩县| 抚顺市| 婺源县| 涞源县| 丹江口市| 景泰县| 沭阳县| 临武县| 温州市| 阜宁县| 会昌县| 苏州市| 文水县| 六安市| 嘉禾县| 定襄县| 普洱| 陇西县| 辽阳市| 雷山县| 凤台县| 海伦市| 翼城县| 广饶县| 都江堰市| 四川省| 阜城县|