CompletableFuture.allOf() 比 CompletableFuture.join() 的循环在等待完成时有什么优势吗?
Has CompletableFuture.allOf() any advantage over a loop with CompletableFuture.join() when just waiting for completion?
我正在对我的数据库进行多次异步调用。我将所有这些异步调用存储在 List<CompletableFuture<X>> list
上。我想一起收集所有结果,所以我需要等待所有这些调用完成。
一种方法是创建一个 CompletableFuture.allOf(list.toArray(...))...
另一种方法是使用:list.stream.map(cf -> cf.join())...
我只是想知道创建全局 CompletableFuture 并等待它完成(当所有单独的 CompletableFuture 完成时)比直接等待单独的 CompletableFutures 完成是否有任何优势。
main
线程被阻塞。
static CompletableFuture<Void> getFailingCF() {
return CompletableFuture.runAsync(() -> {
System.out.println("getFailingCF :: Started getFailingCF.. ");
throw new RuntimeException("getFailingCF:: Failed");
});
}
static CompletableFuture<Void> getOkCF() {
return CompletableFuture.runAsync(() -> {
System.out.println("getOkCF :: Started getOkCF.. ");
LockSupport.parkNanos(TimeUnit.SECONDS.toNanos(3));
System.out.println("getOkCF :: Completed getOkCF.. ");
});
}
public static void main(String[] args) {
List<CompletableFuture<Void>> futures = new ArrayList<>();
futures.add(getFailingCF());
futures.add(getOkCF());
// using CompletableFuture.allOf
var allOfCF = CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]));
allOfCF.join();
// invoking join on individual CF
futures.stream()
.map(CompletableFuture::join)
.collect(Collectors.toList());
}
在上面的代码片段中,区别在于处理异常:CompletableFuture.allOf(..)
包装任何 CompletableFuture
抛出的异常,同时允许其余线程(执行 CompletableFuture
) 继续执行。
list.stream.map(cf -> cf.join())...
方式立即抛出异常并终止应用程序(以及执行列表中CF的所有线程)。
请注意,在 allOf
上调用 join()
也会抛出包装异常。它还将终止该应用程序。但是,此时,与 list.stream.map(cf -> cf.join())...
不同的是,其余线程已完成处理。
allOfCF.whenComplete(..)
是处理所有CF的执行结果(正常或异常)的优雅方式之一:
allOfCF.whenComplete((v, ex) -> {
System.out.println("In whenComplete...");
System.out.println("----------- Exception Status ------------");
System.out.println(" 1: " + futures.get(0).isCompletedExceptionally());
System.out.println(" 2: " + futures.get(1).isCompletedExceptionally());
});
在 list.stream.map(cf -> cf.join())...
方式中,需要将 join()
调用包装在 try/catch
.
中
我正在对我的数据库进行多次异步调用。我将所有这些异步调用存储在 List<CompletableFuture<X>> list
上。我想一起收集所有结果,所以我需要等待所有这些调用完成。
一种方法是创建一个 CompletableFuture.allOf(list.toArray(...))...
另一种方法是使用:list.stream.map(cf -> cf.join())...
我只是想知道创建全局 CompletableFuture 并等待它完成(当所有单独的 CompletableFuture 完成时)比直接等待单独的 CompletableFutures 完成是否有任何优势。
main
线程被阻塞。
static CompletableFuture<Void> getFailingCF() {
return CompletableFuture.runAsync(() -> {
System.out.println("getFailingCF :: Started getFailingCF.. ");
throw new RuntimeException("getFailingCF:: Failed");
});
}
static CompletableFuture<Void> getOkCF() {
return CompletableFuture.runAsync(() -> {
System.out.println("getOkCF :: Started getOkCF.. ");
LockSupport.parkNanos(TimeUnit.SECONDS.toNanos(3));
System.out.println("getOkCF :: Completed getOkCF.. ");
});
}
public static void main(String[] args) {
List<CompletableFuture<Void>> futures = new ArrayList<>();
futures.add(getFailingCF());
futures.add(getOkCF());
// using CompletableFuture.allOf
var allOfCF = CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]));
allOfCF.join();
// invoking join on individual CF
futures.stream()
.map(CompletableFuture::join)
.collect(Collectors.toList());
}
在上面的代码片段中,区别在于处理异常:CompletableFuture.allOf(..)
包装任何 CompletableFuture
抛出的异常,同时允许其余线程(执行 CompletableFuture
) 继续执行。
list.stream.map(cf -> cf.join())...
方式立即抛出异常并终止应用程序(以及执行列表中CF的所有线程)。
请注意,在 allOf
上调用 join()
也会抛出包装异常。它还将终止该应用程序。但是,此时,与 list.stream.map(cf -> cf.join())...
不同的是,其余线程已完成处理。
allOfCF.whenComplete(..)
是处理所有CF的执行结果(正常或异常)的优雅方式之一:
allOfCF.whenComplete((v, ex) -> {
System.out.println("In whenComplete...");
System.out.println("----------- Exception Status ------------");
System.out.println(" 1: " + futures.get(0).isCompletedExceptionally());
System.out.println(" 2: " + futures.get(1).isCompletedExceptionally());
});
在 list.stream.map(cf -> cf.join())...
方式中,需要将 join()
调用包装在 try/catch
.