天天看點

利用Java8中的CompletableFuture進行異步程式設計

CompletableFuture 是 Java 8 引入的一種用于處理異步程式設計的工具。它提供了一種非常靈活而且易于使用的方式來處理并發任務,能夠簡化代碼的編寫,并提高程式的性能。

CompletableFuture 類實作了 Future 和 CompletionStage 接口,是以可以用來表示一個異步計算的結果,還可以在計算完成後執行一些操作。下面将詳細介紹 CompletableFuture 的使用和一些常見的應用場景。

一、基本用法

1、建立 CompletableFuture 對象

CompletableFuture 可以通過以下方式進行建立:

CompletableFuture<T> future = new CompletableFuture<>();
           

2、執行異步任務

可以使用線程池執行異步任務,并設定任務執行完畢後的回調函數:

CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
    // 異步任務的具體邏輯
}, executor);
           

這裡的 executor 是一個可選的參數,可以指定線程池,如果不指定,則使用預設的 ForkJoinPool 線程池。

3、擷取異步任務的結果

可以使用 get() 方法來擷取異步任務的結果,注意這是一個阻塞方法,會一直等待任務完成:

T result = future.get();
           

4、處理任務的執行結果

可以使用 thenAccept()、thenApply()、thenRun() 等方法對任務的執行結果進行處理,這些方法都接受一個回調函數作為參數,任務完成後會觸發回調函數的執行。

5、異常處理

可以使用 exceptionally() 方法來處理任務執行過程中出現的異常:

CompletableFuture<T> future = CompletableFuture.supplyAsync(() -> {
    // 執行可能會抛出異常的代碼
}).exceptionally(ex -> {
    // 異常處理邏輯
    return defaultValue;
});
           

二、組合多個 CompletableFuture

1、thenCompose()

通過 thenCompose() 方法可以将兩個 CompletableFuture 對象串聯起來,将一個任務的結果作為另一個任務的輸入:

CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(() -> 10);
CompletableFuture<Integer> future2 = future1.thenCompose(result -> CompletableFuture.supplyAsync(() -> result * 2));
           

這樣,當 future1 完成時,它的結果會被傳遞給 future2 進行進一步處理。

利用Java8中的CompletableFuture進行異步程式設計

2、thenCombine()

通過 thenCombine() 方法可以将兩個 CompletableFuture 對象的結果進行合并處理:

CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(() -> 10);
CompletableFuture<Integer> future2 = CompletableFuture.supplyAsync(() -> 20);
CompletableFuture<Integer> combinedFuture = future1.thenCombine(future2, (result1, result2) -> result1 + result2);
           

這裡的回調函數接受 future1 和 future2 的結果,并傳回它們的和。

3、allOf() 和 anyOf()

allOf() 方法接受一個 CompletableFuture 數組作為參數,等待所有的 CompletableFuture 都完成後傳回:

CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(() -> 10);
CompletableFuture<Integer> future2 = CompletableFuture.supplyAsync(() -> 20);
CompletableFuture<Void> allFutures = CompletableFuture.allOf(future1, future2);
           

anyOf() 方法接受一個 CompletableFuture 數組作為參數,等待任意一個 CompletableFuture 完成後傳回:

CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(() -> 10);
CompletableFuture<Integer> future2 = CompletableFuture.supplyAsync(() -> 20);
CompletableFuture<Object> anyFuture = CompletableFuture.anyOf(future1, future2);
           

三、異常處理和逾時

1、exceptionally()

通過 exceptionally() 方法可以處理任務執行過程中出現的異常,傳回一個預設值或者進行其他的異常處理邏輯。

2、handle()

handle() 方法類似于 exceptionally(),但是可以處理任務正常完成後的結果和異常情況。

3、whenComplete()

whenComplete() 方法接收一個 BiConsumer 參數,在任務完成後無論是否出現異常都會被調用,可以對任務的結果進行處理。

4、timeout()

可以使用 completeOnTimeout() 或者 orTimeout() 方法來設定任務的逾時時間。

四、并行流與 CompletableFuture

Java 8 還提供了并行流的功能,可以很友善地将一個集合的操作并行化。結合 CompletableFuture,我們可以更靈活地控制并行任務的執行順序和流程。

五、應用場景

CompletableFuture 可以應用于很多場景,包括:

  • 并發執行多個任務,并等待所有任務完成後進行下一步操作;
  • 異步擷取遠端資料,提高系統性能;
  • 将多個阻塞 IO 操作組合成一個異步任務;
  • 異步調用外部服務或接口。

總結一下,CompletableFuture 提供了一種簡潔而強大的方式來處理異步程式設計。通過組合多個 CompletableFuture 對象,可以實作複雜的任務流程和并發邏輯。它不僅提供了豐富的方法用于處理結果、處理異常和設定逾時,還能與并行流相結合,進一步提高程式的性能。

繼續閱讀