CompletableFuture介紹
CompletableFuture
是Java 8中的一個(gè)很重要的類樊卓,它是一個(gè)實(shí)現(xiàn)了 Future
接口的異步處理類惑朦,可以幫助我們更加方便地執(zhí)行異步任務(wù)和處理異步任務(wù)的結(jié)果蝙云。 CompletableFuture
的底層實(shí)現(xiàn)是基于 Fork/Join
框架和 ConcurrentLinkedQueue
凭语,在Java 8中幸缕, CompletableFuture
是在 java.util.concurrent
包下涵亏。
CompletableFuture底層實(shí)現(xiàn)
CompletableFuture
底層依賴了 Fork/Join
框架和 ConcurrentLinkedQueue
。 Fork/Join
框架是Java 7加入的一個(gè)框架雷蹂,它的基本思想是將一個(gè)大任務(wù)拆成多個(gè)小任務(wù)并行執(zhí)行伟端,最后將結(jié)果合并起來。而 ConcurrentLinkedQueue
是Java 5中添加的一個(gè)線程安全的隊(duì)列匪煌,它支持高并發(fā)下的并發(fā)讀寫责蝠。
CompletableFuture
底層的異步處理也是基于這兩個(gè)框架的党巾。異步任務(wù)的執(zhí)行,是將任務(wù)拆分成多個(gè)小任務(wù)霜医,然后并行執(zhí)行齿拂,最后合并結(jié)果。同時(shí)肴敛,異步任務(wù)的結(jié)果可以是不同類型的對(duì)象署海,如 void
、 value
和 exception
等医男。
CompletableFuture API
CompletableFuture
類中提供了很多API砸狞,常見的有以下幾個(gè):
創(chuàng)建CompletableFuture
我們可以通過以下兩種方式創(chuàng)建CompletableFuture
:
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> "Hello World");
CompletableFuture<String> future2 = CompletableFuture.completedFuture("Hello World");
如果需要無返回值的CompletableFuture,可以通過以下方式:
CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
// 做一些不需要返回值的操作
});
在這個(gè)示例中镀梭,我們創(chuàng)建了一個(gè) CompletableFuture
對(duì)象刀森,它使用 runAsync()
方法執(zhí)行了一個(gè)不需要返回值的操作。注意报账,這個(gè)操作是在新的線程中執(zhí)行的研底,因此不會(huì)阻塞主線程。
可以通過調(diào)用 future.join()
來等待這個(gè)異步任務(wù)的完成透罢。如果不需要等待任務(wù)的完成榜晦,可以直接返回 future
對(duì)象。
通過 supplyAsync
方式創(chuàng)建的CompletableFuture
羽圃,會(huì)執(zhí)行一個(gè)異步任務(wù)乾胶,并返回結(jié)果。而 completedFuture
方式創(chuàng)建的CompletableFuture
统屈,則直接返回一個(gè)已經(jīng)完成的CompletableFuture
對(duì)象胚吁。
異步任務(wù)之間的關(guān)系
CompletableFuture
中有很多方法可以用來描述異步任務(wù)之間的關(guān)系,如:
- thenApply
- thenAccept
- thenRun
- thenCompose
- thenCombine
- whenComplete
這些方法的使用方式相似愁憔,都是通過鏈?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
中的代碼超凳,無論成功或失敗都會(huì)執(zhí)行愈污。
異常處理
CompletableFuture
中有很多方法可以用來處理異步任務(wù)中出現(xiàn)的異常,如:
- exceptionally
- handle
這些方法的使用方式相似轮傍,都是通過鏈?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ù)完成后擎析,無論成功或失敗都會(huì)執(zhí)行,并可以處理異常信息挥下。
CompletableFuture用法示例
創(chuàng)建CompletableFuture
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> "Hello World");
通過 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
。