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 、 value 和 exception 等。
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ì)在future和future5任務(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é)果為 Error 或 Hello World 。