Java中的CompletableFuture核心用法和常見場(chǎng)景
1、引言
CompletableFuture 是 Java 8 引入的一個(gè)非常強(qiáng)大的異步編程工具,屬于 java.util.concurrent 包。它不僅支持異步執(zhí)行任務(wù),還支持任務(wù)的組合、異常處理、回調(diào)等豐富的操作。下面我會(huì)詳細(xì)介紹 CompletableFuture 的核心用法和常見場(chǎng)景。
2. 基本概念
- Future:早期的異步結(jié)果表示,功能有限,只能通過(guò)
get()阻塞獲取結(jié)果。 - CompletableFuture:增強(qiáng)版的 Future,支持鏈?zhǔn)疆惒骄幊?、組合、異常處理、回調(diào)等。
3. 創(chuàng)建 CompletableFuture
3.1. 手動(dòng)創(chuàng)建
CompletableFuture<String> future = new CompletableFuture<>();
// 可以手動(dòng)完成
future.complete("Hello");3.2. 通過(guò)靜態(tài)工廠方法
supplyAsync:有返回值,異步執(zhí)行runAsync:無(wú)返回值,異步執(zhí)行
CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> {
// 模擬耗時(shí)操作
return "Hello CompletableFuture";
});
CompletableFuture<Void> future2 = CompletableFuture.runAsync(() -> {
// 執(zhí)行某些操作
});4. 獲取結(jié)果
get():阻塞等待結(jié)果join():類似于get(),但遇到異常會(huì)拋出 unchecked 異常
String result = future1.get(); // 可能拋出異常 String result2 = future1.join(); // RuntimeException
5. 回調(diào)和鏈?zhǔn)讲僮?/h2>
5.1. thenApply / thenApplyAsync
對(duì)結(jié)果進(jìn)行轉(zhuǎn)換(有返回值)
CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> 100)
.thenApply(i -> i + 10); // 結(jié)果為1105.2. thenAccept / thenAcceptAsync
對(duì)結(jié)果做處理,無(wú)返回值
CompletableFuture.supplyAsync(() -> "hello")
.thenAccept(s -> System.out.println(s));5.3. thenRun / thenRunAsync
無(wú)參數(shù)、無(wú)返回值,僅執(zhí)行后續(xù)操作
CompletableFuture.supplyAsync(() -> "hello")
.thenRun(() -> System.out.println("任務(wù)執(zhí)行完畢"));6. 任務(wù)組合
5.1. thenCombine / thenCombineAsync
兩個(gè)任務(wù)都完成后,合并結(jié)果
CompletableFuture<Integer> f1 = CompletableFuture.supplyAsync(() -> 10); CompletableFuture<Integer> f2 = CompletableFuture.supplyAsync(() -> 20); CompletableFuture<Integer> result = f1.thenCombine(f2, (a, b) -> a + b); // 30
6.2. thenCompose / thenComposeAsync
任務(wù)依賴,前一個(gè)結(jié)果作為后一個(gè)輸入
CompletableFuture<String> f = CompletableFuture.supplyAsync(() -> "Hello")
.thenCompose(s -> CompletableFuture.supplyAsync(() -> s + " World"));6.3. allOf / anyOf
等待多個(gè)任務(wù)全部/任一完成
CompletableFuture<Void> all = CompletableFuture.allOf(f1, f2); all.join(); // 等待全部完成 CompletableFuture<Object> any = CompletableFuture.anyOf(f1, f2); Object fastest = any.join(); // 任意一個(gè)完成即可
7. 異常處理
7.1. exceptionally
捕獲異常,返回默認(rèn)值
CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
throw new RuntimeException("出錯(cuò)了");
}).exceptionally(e -> {
System.out.println(e.getMessage());
return 0;
});7.2. handle / handleAsync
無(wú)論成功或失敗都處理
CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
throw new RuntimeException("出錯(cuò)了");
}).handle((result, ex) -> {
if (ex != null) {
System.out.println(ex.getMessage());
return 0;
}
return result;
});8. 自定義線程池
默認(rèn)使用 ForkJoinPool.commonPool(),可以自定義線程池:
ExecutorService executor = Executors.newFixedThreadPool(2); CompletableFuture.supplyAsync(() -> "hello", executor);
9. 實(shí)用示例
9.1. 多個(gè)異步任務(wù)并發(fā)執(zhí)行,最后匯總
CompletableFuture<String> f1 = CompletableFuture.supplyAsync(() -> "A");
CompletableFuture<String> f2 = CompletableFuture.supplyAsync(() -> "B");
CompletableFuture<String> f3 = CompletableFuture.supplyAsync(() -> "C");
CompletableFuture<Void> all = CompletableFuture.allOf(f1, f2, f3);
all.thenRun(() -> {
try {
System.out.println(f1.get() + f2.get() + f3.get());
} catch (Exception e) {
e.printStackTrace();
}
});10. 注意事項(xiàng)
- 盡量避免阻塞(如
get()),推薦使用回調(diào)。 - 注意線程池資源,合理分配,避免 OOM。
- 處理好異常,避免線程池線程被異常吞掉。
11. 進(jìn)階用法
11.1. 串聯(lián)和并聯(lián)任務(wù)
串聯(lián)(依賴關(guān)系)
當(dāng)一個(gè)任務(wù)的結(jié)果依賴于另一個(gè)任務(wù)時(shí),使用 thenCompose:
CompletableFuture<String> getUserId = CompletableFuture.supplyAsync(() -> "user123");
CompletableFuture<String> getUserInfo = getUserId.thenCompose(id ->
CompletableFuture.supplyAsync(() -> "用戶信息:" + id)
);并聯(lián)(聚合結(jié)果)
多個(gè)任務(wù)并發(fā)執(zhí)行,最后聚合結(jié)果:
CompletableFuture<Integer> t1 = CompletableFuture.supplyAsync(() -> 1);
CompletableFuture<Integer> t2 = CompletableFuture.supplyAsync(() -> 2);
CompletableFuture<Integer> t3 = CompletableFuture.supplyAsync(() -> 3);
CompletableFuture<List<Integer>> all = CompletableFuture.allOf(t1, t2, t3)
.thenApply(v -> {
List<Integer> result = new ArrayList<>();
result.add(t1.join());
result.add(t2.join());
result.add(t3.join());
return result;
});11.2. 超時(shí)控制
Java 9 后,CompletableFuture 增加了超時(shí)相關(guān)方法:
future.orTimeout(3, TimeUnit.SECONDS)
.exceptionally(ex -> {
System.out.println("超時(shí)啦");
return null;
});或自己實(shí)現(xiàn):
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
Thread.sleep(5000);
return "hello";
});
try {
String result = future.get(2, TimeUnit.SECONDS); // 2秒超時(shí)
} catch (TimeoutException e) {
System.out.println("超時(shí)了");
}11.3. 異步流水線
你可以鏈?zhǔn)降亟M合多個(gè)異步操作,形成“流水線”:
CompletableFuture.supplyAsync(() -> "A")
.thenApply(s -> s + "B")
.thenApply(s -> s + "C")
.thenAccept(System.out::println); // 輸出 ABC11.4. 處理異常和兜底方案
推薦使用 handle 或 exceptionally 做兜底:
CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
throw new RuntimeException("出錯(cuò)了");
})
.handle((result, ex) -> ex == null ? result : -1);11.5. 自定義線程池的好處
- 控制線程數(shù)量,避免公共線程池被占滿。
- 適合高并發(fā)、IO密集型場(chǎng)景。
ExecutorService executor = Executors.newFixedThreadPool(10); CompletableFuture.supplyAsync(() -> "業(yè)務(wù)邏輯", executor);
12. 實(shí)戰(zhàn)場(chǎng)景舉例
12.1. 微服務(wù)并發(fā)調(diào)用
假設(shè)要并發(fā)調(diào)用三個(gè)微服務(wù)接口,最后聚合結(jié)果:
CompletableFuture<String> api1 = CompletableFuture.supplyAsync(() -> callApi1());
CompletableFuture<String> api2 = CompletableFuture.supplyAsync(() -> callApi2());
CompletableFuture<String> api3 = CompletableFuture.supplyAsync(() -> callApi3());
CompletableFuture<Void> all = CompletableFuture.allOf(api1, api2, api3);
all.thenAccept(v -> {
String r1 = api1.join();
String r2 = api2.join();
String r3 = api3.join();
System.out.println("聚合結(jié)果:" + r1 + r2 + r3);
});12.2. 異步寫數(shù)據(jù)庫(kù)+異步發(fā)消息
CompletableFuture<Void> saveDb = CompletableFuture.runAsync(() -> saveToDb());
CompletableFuture<Void> sendMsg = CompletableFuture.runAsync(() -> sendMsg());
CompletableFuture.allOf(saveDb, sendMsg)
.thenRun(() -> System.out.println("所有操作完成"));13. 常見問(wèn)題與建議
- 線程池泄漏:線程池要合理關(guān)閉,避免資源泄漏。
- 異常未處理:建議所有鏈路最后加
.exceptionally或.handle。 - 阻塞等待:盡量用回調(diào)而不是
get()或join()。 - 鏈?zhǔn)讲僮?/strong>:推薦鏈?zhǔn)骄幊?,代碼更清晰。
總結(jié)
CompletableFuture 是 Java 異步編程的利器,支持豐富的組合、回調(diào)和異常處理能力。合理使用可以極大提升程序的并發(fā)能力和響應(yīng)速度。
到此這篇關(guān)于Java中的CompletableFuture核心用法和常見場(chǎng)景的文章就介紹到這了,更多相關(guān)java completablefuture使用內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- Java使用CompletableFuture實(shí)現(xiàn)異步編程
- java使用CompletableFuture分批處理任務(wù)實(shí)現(xiàn)
- Java CompletableFuture使用方式
- Java中的CompletableFuture使用解析
- Java并發(fā)編程中的CompletableFuture使用詳解
- java異步編程CompletableFuture使用示例詳解
- Java多線程工具CompletableFuture的使用教程
- 詳解Java CompletableFuture使用方法以及與FutureTask的區(qū)別
- Java CompletableFuture的使用詳解
相關(guān)文章
Java 實(shí)戰(zhàn)練手項(xiàng)目之醫(yī)院預(yù)約掛號(hào)系統(tǒng)的實(shí)現(xiàn)流程
讀萬(wàn)卷書不如行萬(wàn)里路,只學(xué)書上的理論是遠(yuǎn)遠(yuǎn)不夠的,只有在實(shí)戰(zhàn)中才能獲得能力的提升,本篇文章手把手帶你用java+SpringBoot+Maven+Vue+mysql實(shí)現(xiàn)一個(gè)醫(yī)院預(yù)約掛號(hào)系統(tǒng),大家可以在過(guò)程中查缺補(bǔ)漏,提升水平2021-11-11
jetty運(yùn)行時(shí)無(wú)法保存文件的解決方法
這篇文章主要為大家詳細(xì)介紹了jetty運(yùn)行時(shí)無(wú)法保存文件的解決方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-11-11
Java使用ShardingSphere實(shí)現(xiàn)數(shù)據(jù)庫(kù)分片的策略指南
隨著業(yè)務(wù)數(shù)據(jù)量的爆炸式增長(zhǎng),數(shù)據(jù)庫(kù)分片作為解決大數(shù)據(jù)量存儲(chǔ)和查詢性能問(wèn)題的核心技術(shù),已成為現(xiàn)代分布式系統(tǒng)架構(gòu)的重要組成部分,ShardingSphere作為一套開源的分布式數(shù)據(jù)庫(kù)解決方案,提供了強(qiáng)大的數(shù)據(jù)分片功能,本文將深入探討ShardingSphere的核心分片策略2025-08-08
spring?boot配置dubbo方式(properties)
這篇文章主要介紹了spring?boot配置dubbo方式(properties),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-01-01
tio-http-server打包為二進(jìn)制文件的實(shí)現(xiàn)及優(yōu)勢(shì)詳解
這篇文章主要為大家介紹了tio-http-server打包為二進(jìn)制文件實(shí)現(xiàn)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-12-12
java9的JShell小工具和編譯器兩種自動(dòng)優(yōu)化方法
這篇文章主要介紹了java9的JShell小工具和編譯器兩種自動(dòng)優(yōu)化方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-07-07
詳解Spring Cloud Gateway基于服務(wù)發(fā)現(xiàn)的默認(rèn)路由規(guī)則
這篇文章主要介紹了詳解Spring Cloud Gateway基于服務(wù)發(fā)現(xiàn)的默認(rèn)路由規(guī)則,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2019-05-05

