如何使用CompletableFuture

CompletableFuture介紹

CompletableFuture 是Java 8中的一個(gè)很重要的類(lèi),它是一個(gè)實(shí)現(xiàn)了 Future 接口的異步處理類(lèi),可以幫助我們更加方便地執(zhí)行異步任務(wù)和處理異步任務(wù)的結(jié)果。 CompletableFuture 的底層實(shí)現(xiàn)是基于 Fork/Join 框架和 ConcurrentLinkedQueue ,在Java 8中, CompletableFuture 是在 java.util.concurrent 包下。

CompletableFuture底層實(shí)現(xiàn)

CompletableFuture 底層依賴(lài)了 Fork/Join 框架和 ConcurrentLinkedQueue 。 Fork/Join 框架是Java 7加入的一個(gè)框架,它的基本思想是將一個(gè)大任務(wù)拆成多個(gè)小任務(wù)并行執(zhí)行,最后將結(jié)果合并起來(lái)。而 ConcurrentLinkedQueue 是Java 5中添加的一個(gè)線程安全的隊(duì)列,它支持高并發(fā)下的并發(fā)讀寫(xiě)。
CompletableFuture 底層的異步處理也是基于這兩個(gè)框架的。異步任務(wù)的執(zhí)行,是將任務(wù)拆分成多個(gè)小任務(wù),然后并行執(zhí)行,最后合并結(jié)果。同時(shí),異步任務(wù)的結(jié)果可以是不同類(lèi)型的對(duì)象,如 void 、 valueexception 等。

CompletableFuture API

CompletableFuture 類(lèi)中提供了很多API,常見(jiàn)的有以下幾個(gè):

創(chuàng)建CompletableFuture

我們可以通過(guò)以下兩種方式創(chuàng)建CompletableFuture

CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> "Hello World");
CompletableFuture<String> future2 = CompletableFuture.completedFuture("Hello World");

如果需要無(wú)返回值的CompletableFuture,可以通過(guò)以下方式:

CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
    // 做一些不需要返回值的操作
});

在這個(gè)示例中,我們創(chuàng)建了一個(gè) CompletableFuture 對(duì)象,它使用 runAsync() 方法執(zhí)行了一個(gè)不需要返回值的操作。注意,這個(gè)操作是在新的線程中執(zhí)行的,因此不會(huì)阻塞主線程。

可以通過(guò)調(diào)用 future.join() 來(lái)等待這個(gè)異步任務(wù)的完成。如果不需要等待任務(wù)的完成,可以直接返回 future 對(duì)象。

通過(guò) supplyAsync 方式創(chuàng)建的CompletableFuture,會(huì)執(zhí)行一個(gè)異步任務(wù),并返回結(jié)果。而 completedFuture 方式創(chuàng)建的CompletableFuture,則直接返回一個(gè)已經(jīng)完成的CompletableFuture對(duì)象。

異步任務(wù)之間的關(guān)系

CompletableFuture 中有很多方法可以用來(lái)描述異步任務(wù)之間的關(guān)系,如:

  • thenApply
  • thenAccept
  • thenRun
  • thenCompose
  • thenCombine
  • whenComplete

這些方法的使用方式相似,都是通過(guò)鏈?zhǔn)秸{(diào)用的方式,如下示例:

CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> "Hello World");
CompletableFuture<String> future2 = future.thenApply(str -> str + "Java");
CompletableFuture<Void> future3 = future.thenAccept(str -> System.out.println(str));
CompletableFuture<Void> future4 = future.thenRun(() -> System.out.println("Hello Java"));
CompletableFuture<String> future5 = future.thenCompose(str -> CompletableFuture.completedFuture(str + "Java"));
CompletableFuture<String> future6 = future.thenCombine(future5, (str1, str2) -> str1 + str2);
CompletableFuture<Void> future7 = future.whenComplete((str, ex) -> {
    if (ex != null) {
        System.out.println("Error: " + ex.getMessage());
    } else {
        System.out.println(str);
    }
});
  • thenApply 方法會(huì)在 future 任務(wù)完成后,將其結(jié)果作為參數(shù)傳遞給 thenApply 中的函數(shù),返回另一個(gè) CompletableFuture
  • thenAccept 方法會(huì)在 future 任務(wù)完成后,將其結(jié)果作為參數(shù)傳遞給 thenAccept 中的函數(shù),不返回任何結(jié)果。
  • thenRun 方法會(huì)在 future 任務(wù)完成后,執(zhí)行 thenRun 中的代碼,不接受任何參數(shù),也不返回任何結(jié)果。
  • thenCompose 方法會(huì)在 future 任務(wù)完成后,將其結(jié)果作為參數(shù)傳遞給 thenCompose 中的 CompletableFuture ,返回另一個(gè) CompletableFuture 。
  • thenCombine 方法會(huì)在 futurefuture5 任務(wù)都完成后,將兩個(gè)任務(wù)的結(jié)果作為參數(shù)傳遞給 thenCombine 中的函數(shù),返回另一個(gè) CompletableFuture 。
  • whenComplete 方法會(huì)在 future 任務(wù)完成后,執(zhí)行 whenComplete 中的代碼,無(wú)論成功或失敗都會(huì)執(zhí)行。

異常處理

CompletableFuture 中有很多方法可以用來(lái)處理異步任務(wù)中出現(xiàn)的異常,如:

  • exceptionally
  • handle

這些方法的使用方式相似,都是通過(guò)鏈?zhǔn)秸{(diào)用的方式,如下示例:

CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
    if (System.currentTimeMillis() % 2 == 0) {
        throw new RuntimeException();
    }
    return "Hello World";
});
 CompletableFuture<String> future2 = future.exceptionally(ex -> "Error")
                                           .thenApply(str -> str + " Java");
 CompletableFuture<String> future3 = future.handle((str, ex) -> {
    if (ex != null) {
        System.out.println("Error: " + ex.getMessage());
        return "Error";
    } else {
        return str;
    }
});
  • exceptionally 方法會(huì)在 future 任務(wù)出現(xiàn)異常的時(shí)候執(zhí)行,并返回一個(gè)帶有默認(rèn)值的 CompletableFuture
  • handle 方法會(huì)在 future 任務(wù)完成后,無(wú)論成功或失敗都會(huì)執(zhí)行,并可以處理異常信息。

CompletableFuture用法示例

創(chuàng)建CompletableFuture

CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> "Hello World");

通過(guò) supplyAsync 創(chuàng)建一個(gè)異步執(zhí)行任務(wù),返回值為 Hello World 。

異步任務(wù)之間的關(guān)系

  • thenApply 示例
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> "Hello World");
CompletableFuture<String> future2 = future.thenApply(str -> str + " Java");
System.out.println(future2.get());

輸出結(jié)果為 Hello World Java 。

  • thenAccept 示例
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> "Hello World");
CompletableFuture<Void> future2 = future.thenAccept(str -> System.out.println(str + " Java"));
future2.get();

輸出結(jié)果為 Hello World Java 。

  • thenRun 示例
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> "Hello World");
CompletableFuture<Void> future2 = future.thenRun(() -> System.out.println("Hello Java"));
future2.get();

輸出結(jié)果為 Hello Java

  • thenCompose 示例
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> "Hello World");
CompletableFuture<String> future2 = future.thenCompose(str -> CompletableFuture.completedFuture(str + " Java"));
System.out.println(future2.get());

輸出結(jié)果為 Hello World Java

  • thenCombine 示例
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> "Hello");
CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> " World");
CompletableFuture<String> future3 = future.thenCombine(future2, (str1, str2) -> str1 + str2);
System.out.println(future3.get());

輸出結(jié)果為 Hello World 。

  • whenComplete 示例
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> "Hello World");
CompletableFuture<Void> future2 = future.whenComplete((str, ex) -> {
    if (ex != null) {
        System.out.println("Error: " + ex.getMessage());
    } else {
        System.out.println(str);
    }
});
future2.get();

輸出結(jié)果為 Hello World

異常處理示例

  • exceptionally 示例
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
    if (System.currentTimeMillis() % 2 == 0) {
        throw new RuntimeException();
    }
    return "Hello World";
});
 CompletableFuture<String> future2 = future.exceptionally(ex -> "Error").thenApply(str -> str + " Java");
System.out.println(future2.get());

輸出結(jié)果為 Error Java 。

  • handle 示例
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
    if (System.currentTimeMillis() % 2 == 0) {
        throw new RuntimeException();
    }
    return "Hello World";
});
 CompletableFuture<String> future2 = future.handle((str, ex) -> {
    if (ex != null) {
        System.out.println("Error: " + ex.getMessage());
        return "Error";
    } else {
        return str;
    }
});
System.out.println(future2.get());

輸出結(jié)果為 ErrorHello World 。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容