正確使用Java?CompletableFuture對(duì)象的方法
1 什么是 CompletableFuture?
CompletableFuture 是 Java 8 引入的一個(gè)強(qiáng)大的異步編程工具。允許以聲明式的方式處理異步任務(wù)的結(jié)果,避免了傳統(tǒng)回調(diào)和手動(dòng)管理線程的復(fù)雜性。
CompletableFuture 可以組合和鏈?zhǔn)秸{(diào)用,高效地利用多核處理器的能力,并且減少了傳統(tǒng)并發(fā)編程中常見的競(jìng)態(tài)條件和死鎖等問(wèn)題。
在日常開發(fā)中,經(jīng)常需要處理那些可能耗時(shí)的任務(wù),比如網(wǎng)絡(luò)請(qǐng)求、數(shù)據(jù)庫(kù)查詢或者復(fù)雜的計(jì)算。使用 CompletableFuture,可以告訴程序如何在后臺(tái)執(zhí)行這些任務(wù),然后在任務(wù)完成后執(zhí)行特定的操作。
可以想象一下,CompletableFuture 就像是一條可以穿越時(shí)間的信使,你可以把一項(xiàng)任務(wù)托付給它,然后繼續(xù)做其他事情。當(dāng)任務(wù)完成時(shí),它會(huì)及時(shí)將結(jié)果送回來(lái),讓你可以立即處理。這樣,你就不必在等待任務(wù)完成的過(guò)程中浪費(fèi)時(shí)間,而是可以更高效地利用自己的資源。
2 如何正確使用 CompletableFuture 對(duì)象?
CompletableFuture 可以以一種非阻塞的方式執(zhí)行異步任務(wù),并能夠在任務(wù)完成后立即得到通知。通過(guò)鏈?zhǔn)秸{(diào)用的方式,可以很方便地組合多個(gè)異步操作,處理它們的結(jié)果或者異常。
通過(guò) CompletableFuture.supplyAsync() 方法創(chuàng)建一個(gè) CompletableFuture 對(duì)象,并指定一個(gè)需要異步執(zhí)行的任務(wù):
// Supplier 函數(shù)會(huì)在一個(gè)新的線程上異步執(zhí)行
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
// 模擬一個(gè)耗時(shí)操作,如從數(shù)據(jù)庫(kù)中讀取數(shù)據(jù)
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "異步任務(wù)完成";
});
通過(guò)在 CompletableFuture 上添加一些操作,比如處理任務(wù)的結(jié)果或者處理任務(wù)執(zhí)行過(guò)程中可能發(fā)生的異常:
// thenAccept()方法接收一個(gè) Consumer 函數(shù)
future.thenAccept(result -> {
System.out.println("任務(wù)完成,結(jié)果為:" + result);
}).exceptionally(ex -> {
System.out.println("任務(wù)出現(xiàn)異常:" + ex.getMessage());
return null;
});
3 如何結(jié)合回調(diào)函數(shù)處理異步任務(wù)結(jié)果?
結(jié)合回調(diào)函數(shù)處理異步任務(wù)結(jié)果的過(guò)程可以比作在等待一份重要的快遞時(shí)安排一個(gè)通知服務(wù)。這個(gè)通知服務(wù)就是回調(diào)函數(shù),它會(huì)在快遞送達(dá)時(shí)通知你,或者在處理完成后執(zhí)行特定的操作。
在 Java 的 CompletableFuture 中,這種模式可以通過(guò) supplyAsync() 、thenApply()、thenAccept() 和 handle() 方法來(lái)實(shí)現(xiàn)。
創(chuàng)建一個(gè)異步任務(wù)時(shí),使用 CompletableFuture.supplyAsync() 可以啟動(dòng)一個(gè)任務(wù),這個(gè)任務(wù)在后臺(tái)線程中執(zhí)行,直到它完成。假設(shè)有一個(gè)任務(wù)需要從遠(yuǎn)程服務(wù)器獲取數(shù)據(jù):
// supplyAsync() 方法接收一個(gè) Supplier 函數(shù),這個(gè)函數(shù)會(huì)在后臺(tái)線程中運(yùn)行,并返回一個(gè)結(jié)果
// 結(jié)果會(huì)被封裝在 CompletableFuture 對(duì)象中,等待進(jìn)一步處理
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
// 模擬從遠(yuǎn)程服務(wù)器獲取數(shù)據(jù)
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "數(shù)據(jù)已成功獲取";
});
使用 thenApply() 方法,可以在異步任務(wù)完成后,對(duì)結(jié)果進(jìn)行轉(zhuǎn)換。這個(gè)方法接收一個(gè) Function 函數(shù),這個(gè)函數(shù)會(huì)接收任務(wù)的結(jié)果,并返回一個(gè)新結(jié)果。比如,將獲取的數(shù)據(jù)進(jìn)行處理:
// thenApply() 方法將原始數(shù)據(jù)轉(zhuǎn)換為大寫形式
// 處理后的結(jié)果會(huì)成為新的 CompletableFuture 對(duì)象的結(jié)果
CompletableFuture<String> processedFuture = future.thenApply(result -> {
// 對(duì)結(jié)果進(jìn)行處理
return result.toUpperCase();
});
為了執(zhí)行一個(gè)操作而不關(guān)心處理的結(jié)果,可以使用 thenAccept() 方法。這個(gè)方法接收一個(gè) Consumer 函數(shù),它處理任務(wù)完成時(shí)的結(jié)果,可以在異步任務(wù)完成時(shí)執(zhí)行一些操作,比如日志記錄或通知用戶。例如,將結(jié)果打印到控制臺(tái):
// 在任務(wù)完成后會(huì)調(diào)用傳入的 Consumer 函數(shù),并將結(jié)果傳遞給它
future.thenAccept(result -> {
System.out.println("任務(wù)完成,結(jié)果是:" + result);
});
在任務(wù)執(zhí)行過(guò)程中,可能會(huì)遇到異常。handle() 方法可以用來(lái)處理這些異常,它接收一個(gè) BiFunction 函數(shù),這個(gè)函數(shù)接收結(jié)果和異常(如果有的話),并返回一個(gè)處理后的結(jié)果。例如:
// handle() 方法檢查是否有異常發(fā)生
// 如果有異常,它會(huì)處理異常并返回一個(gè)默認(rèn)的結(jié)果
// 如果沒(méi)有異常,它會(huì)處理正常的結(jié)果
CompletableFuture<String> handledFuture = future.handle((result, ex) -> {
if (ex != null) {
// 處理異常
System.out.println("任務(wù)發(fā)生錯(cuò)誤:" + ex.getMessage());
return "錯(cuò)誤處理結(jié)果";
}
// 處理正常結(jié)果
return result.toLowerCase();
});
對(duì)于這四種回調(diào)函數(shù),可以使得異步任務(wù)的結(jié)果處理變得靈活而強(qiáng)大。通過(guò)結(jié)合使用不同的回調(diào)函數(shù),可以對(duì)異步任務(wù)的結(jié)果進(jìn)行多種操作,保證程序在處理復(fù)雜任務(wù)時(shí)仍然保持清晰和高效。
4 如何組合并處理多個(gè) CompletableFuture?
組合和處理多個(gè) CompletableFuture 可以讓并發(fā)任務(wù)變得更加靈活和高效。設(shè)想有多個(gè)任務(wù)需要并行執(zhí)行,然后將它們的結(jié)果結(jié)合起來(lái)進(jìn)行進(jìn)一步處理。
在進(jìn)行組合時(shí),最基本的方法之一是將多個(gè) CompletableFuture 的結(jié)果合并。比如,有兩個(gè)任務(wù)需要并行完成,獲取兩個(gè)不同的數(shù)據(jù)源,然后將這兩個(gè)結(jié)果結(jié)合起來(lái)。
可以使用 thenCombine() 方法,它接收兩個(gè) CompletableFuture 和一個(gè)合并函數(shù),兩個(gè) CompletableFuture 必須在相同的線程池中執(zhí)行。
假設(shè)有兩個(gè)任務(wù)分別從不同的 API 獲取數(shù)據(jù):
CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> {
// 模擬從第一個(gè) API 獲取數(shù)據(jù)
return "數(shù)據(jù)1";
});
CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> {
// 模擬從第二個(gè) API 獲取數(shù)據(jù)
return "數(shù)據(jù)2";
});為了將這兩個(gè)結(jié)果結(jié)合起來(lái),可以使用 thenCombine():
// thenCombine() 方法接收兩個(gè) CompletableFuture 和一個(gè)函數(shù),這個(gè)函數(shù)將兩個(gè)任務(wù)的結(jié)果合并成一個(gè)結(jié)果
// 最終的結(jié)果是將兩個(gè)字符串連接在一起
CompletableFuture<String> combinedFuture = future1.thenCombine(future2, (result1, result2) -> {
// 將兩個(gè)結(jié)果結(jié)合成一個(gè)
return result1 + " 和 " + result2;
});
另一個(gè)有用的方法是 allOf()方法。當(dāng)有多個(gè)任務(wù)需要并行執(zhí)行,并且在所有任務(wù)完成后執(zhí)行某個(gè)操作時(shí),allOf() 非常有用。它接收一個(gè) CompletableFuture 數(shù)組,并在所有這些 CompletableFuture 完成時(shí)觸發(fā)。可以用來(lái)等待多個(gè)異步任務(wù)完成,然后執(zhí)行某個(gè)操作:
CompletableFuture<Void> allOfFuture = CompletableFuture.allOf(future1, future2);
要獲取所有任務(wù)的結(jié)果,可以在 allOf() 的結(jié)果上添加一個(gè)回調(diào)函數(shù):
// thenRun() 方法會(huì)在所有任務(wù)完成后執(zhí)行,它不需要處理結(jié)果,只是執(zhí)行某個(gè)操作
allOfFuture.thenRun(() -> {
// 處理所有任務(wù)完成后的操作
try {
String result1 = future1.get();
String result2 = future2.get();
System.out.println("任務(wù)1的結(jié)果: " + result1);
System.out.println("任務(wù)2的結(jié)果: " + result2);
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
});
如果有任務(wù)依賴于另一個(gè)任務(wù)的結(jié)果,可以使用 thenCompose()方法。這種情況下,第二個(gè)任務(wù)會(huì)在第一個(gè)任務(wù)完成后開始執(zhí)行。thenCompose() 方法接收一個(gè)返回 CompletableFuture 的函數(shù),然后將這兩個(gè) CompletableFuture 鏈接起來(lái):
CompletableFuture<String> future3 = future1.thenCompose(result1 -> {
// 使用第一個(gè)任務(wù)的結(jié)果來(lái)創(chuàng)建新的 CompletableFuture
return CompletableFuture.supplyAsync(() -> result1 + " 處理完成");
});
對(duì)于這些方法來(lái)說(shuō),它們?yōu)樘幚矶鄠€(gè)異步任務(wù)提供了強(qiáng)大的工具,使得并發(fā)編程更加高效和靈活。通過(guò)合理使用這些方法,可以實(shí)現(xiàn)復(fù)雜的異步任務(wù)組合和處理邏輯,確保程序的高效執(zhí)行。
到此這篇關(guān)于Java CompletableFuture深入解析的文章就介紹到這了,更多相關(guān)Java CompletableFuture內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- Java CompletableFuture之異步執(zhí)行、鏈?zhǔn)秸{(diào)用、組合多個(gè)Future、異常處理和超時(shí)控制等詳解
- Java CompletableFuture如何實(shí)現(xiàn)超時(shí)功能
- Java使用CompletableFuture實(shí)現(xiàn)異步編程
- Java8 CompletableFuture異步編程解讀
- java使用CompletableFuture分批處理任務(wù)實(shí)現(xiàn)
- Java中的CompletableFuture基本用法
- Java中的CompletableFuture原理與用法
- Java中的CompletableFuture異步編程詳解
- Java中的CompletableFuture詳解
相關(guān)文章
Java實(shí)現(xiàn)markdown格式內(nèi)容轉(zhuǎn)換為word
這篇文章主要為大家簡(jiǎn)單介紹了如何利用Java實(shí)現(xiàn)markdown格式內(nèi)容轉(zhuǎn)換為word文檔,文中的示例代碼簡(jiǎn)潔易懂,有需要的小伙伴可以參考一下2025-03-03
java中調(diào)用GDAL DLL的實(shí)現(xiàn)方法
本篇文章是對(duì)java中調(diào)用GDAL DLL的實(shí)現(xiàn)方法進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-05-05
Java數(shù)據(jù)結(jié)構(gòu)之棧與隊(duì)列實(shí)例詳解
這篇文章主要給大家介紹了關(guān)于Java數(shù)據(jù)結(jié)構(gòu)之棧與隊(duì)列的相關(guān)資料,算是作為用java描述數(shù)據(jù)結(jié)構(gòu)的一個(gè)開始,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2021-11-11
SpringBoot框架DataSource多數(shù)據(jù)源配置方式
這篇文章主要介紹了SpringBoot框架DataSource多數(shù)據(jù)源配置方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-07-07
Mybatis反向工程出現(xiàn)BigDecimal類型問(wèn)題及解決
這篇文章主要介紹了Mybatis反向工程出現(xiàn)BigDecimal類型問(wèn)題及解決,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-09-09
Spring Boot利用@Async異步調(diào)用:ThreadPoolTaskScheduler線程池的優(yōu)雅關(guān)閉詳解
這篇文章主要給大家介紹了關(guān)于Spring Boot利用@Async異步調(diào)用:ThreadPoolTaskScheduler線程池的優(yōu)雅關(guān)閉的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友可以參考借鑒,下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2018-05-05

