![](https://news.xinpengboligang.com/upload/keji/9a33f2b32cd4bab28abede2886e7c698.jpeg)
CompletableFuture.supplyAsync和CompletableFuture.thenCompose都屬於Java CompletableFuture 中的 API ,用於異步編程,但它們在不同的上下文中使用。
CompletableFuture.supplyAsync
- 當我們想要返回 future 的異步計算時,使用 SupplyAsync。它是異步計算鏈的起點。
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
// some computation
return "Result";
});
CompletableFuture.thenCompose
thenCompose是對一個CompletableFuture返回的結果進行後續操作,返回一個新的CompletableFuture。所以當返回結果是CompletableFuture函數,並且希望在另一個異步操作之後鏈接它時,可以使用它。
- thenCompose接受一個函數,給定結果,返回一個新的 CompletableFuture。此方法用於鏈接異步操作的兩個階段,其中第二階段取決於第一階段的結果。
- thenCompose當您需要啟動第二個異步操作(該操作取決於前一個操作的結果)並且您不希望以嵌套 future ( CompletableFuture<CompletableFuture<T>>) 結束時,請使用。
CompletableFuture<CompletableFuture<String>> future = CompletableFuture.supplyAsync(() -> {
// some computation leading to a result
return CompletableFuture.supplyAsync(() -> "Inner Result");
});
CompletableFuture<String> flattenedFuture = future.thenCompose(innerFuture -> innerFuture);
以下是 thenCompose 的主要用法。
- 當第一個操作的結果依賴於第二個操作時,鏈接依賴異步操作。
- 返回一個新的 CompletableFuture:與 thenApply 不同,thenApply用於轉換 CompletableFuture 的結果。
- 類似 FlatMap 的行為:用函數式編程術語來說,它會鏈接多個異步操作,避免嵌套的CompletableFuture結構。
下面舉一個例子:
- 我們需要將一條消息通過email發送給訂閱者。
- 我們需要先獲取訂閱者的email,然後發送email。
- 我們將首先以異步方式從用戶名獲取email,然後編寫第二個 future 來發送消息。
package org.example;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
public class SendEmailToSubscriber {
public static void main(String[] args) throws ExecutionException, InterruptedException {
CompletableFuture<String> finalFuture = getSubscribersEmail("vikas taank")
.thenCompose(email -> sendNewsLetter(email));
// Wait for the final future to complete
System.out.println(finalFuture.get() " to vikas taank email");
}
// Simulates fetching user email asynchronously
private static CompletableFuture<String> getSubscribersEmail(String userId) {
return CompletableFuture.supplyAsync(() -> {
// Assume this is some IO operation to get user email
System.out.println("Fetching email for user " userId);
return "[email protected]";
});
}
// Simulates sending an email asynchronously
private static CompletableFuture<String> sendNewsLetter(String email) {
return CompletableFuture.supplyAsync(() -> {
// Assume this is some IO operation to send email
System.out.println("Sending News Letter to " email);
return "News Letter sent";
});
}
}
組合兩個CompletableFuture例子:
import reactor.core.publisher.Mono;
import java.util.concurrent.CompletableFuture;
public class CompletableFutureUtil {
// Method to transform CompletableFuture<Mono<T>> into CompletableFuture<T>
public static <T> CompletableFuture<T> fromMonoFuture(CompletableFuture<Mono<T>> completableMono) {
return completableMono.thenCompose(Mono::toFuture);
}
// Method to wait for two different CompletableFuture<T> to complete
public static <T1, T2> CompletableFuture<Void> waitForBoth(
CompletableFuture<T1> future1,
CompletableFuture<T2> future2) {
return CompletableFuture.allOf(future1, future2);
}
// Example usage
public static void main(String[] args) {
CompletableFuture<Mono<DomainObject1>> completableFuture1 = CompletableFuture.completedFuture(Mono.just(new DomainObject1()));
CompletableFuture<Mono<DomainObject2>> completableFuture2 = CompletableFuture.completedFuture(Mono.just(new DomainObject2()));
CompletableFuture<DomainObject1> compFuture1 = fromMonoFuture(completableFuture1);
CompletableFuture<DomainObject2> compFuture2 = fromMonoFuture(completableFuture2);
CompletableFuture<Void> combinedFuture = waitForBoth(compFuture1, compFuture2);
// Wait for both futures to complete (blocking call, use cautiously)
combinedFuture.join();
}
}