Ana*_*man 9 java-8 completable-future
我有3个CompletableFutures,所有3个返回不同的数据类型.
我希望创建一个结果对象,它是所有3个期货返回的结果的组合.
所以我目前的工作代码如下所示:
public ClassD getResultClassD() {
ClassD resultClass = new ClassD();
CompletableFuture<ClassA> classAFuture = CompletableFuture.supplyAsync(() -> service.getClassA() );
CompletableFuture<ClassB> classBFuture = CompletableFuture.supplyAsync(() -> service.getClassB() );
CompletableFuture<ClassC> classCFuture = CompletableFuture.supplyAsync(() -> service.getClassC() );
CompletableFuture.allOf(classAFuture, classBFuture, classCFuture)
.thenAcceptAsync(it -> {
ClassA classA = classAFuture.join();
if (classA != null) {
resultClass.setClassA(classA);
}
ClassB classB = classBFuture.join();
if (classB != null) {
resultClass.setClassB(classB);
}
ClassC classC = classCFuture.join();
if (classC != null) {
resultClass.setClassC(classC);
}
});
return resultClass;
}
Run Code Online (Sandbox Code Playgroud)
我的问题是:
我的假设是,因为我正在使用allOf,thenAcceptAsync 这个调用将是非阻塞的.我的理解是对的吗?
这是处理返回不同结果类型的多个期货的正确方法吗?
在其中构建ClassD对象是正确的thenAcceptAsync吗?
joinor getNow方法?Hol*_*ger 10
你的尝试正朝着正确的方向发展,但不正确.您的方法getResultClassD()返回一个已经实例化的类型对象,ClassD任意线程将在该对象上调用修改方法,而不会给调用者getResultClassD()注意.这可能会导致竞争条件,如果修改方法本身不是线程安全的,那么调用者将永远不知道ClassD实例何时可以使用.
一个正确的解决方案是:
public CompletableFuture<ClassD> getResultClassD() {
CompletableFuture<ClassA> classAFuture
= CompletableFuture.supplyAsync(() -> service.getClassA() );
CompletableFuture<ClassB> classBFuture
= CompletableFuture.supplyAsync(() -> service.getClassB() );
CompletableFuture<ClassC> classCFuture
= CompletableFuture.supplyAsync(() -> service.getClassC() );
return CompletableFuture.allOf(classAFuture, classBFuture, classCFuture)
.thenApplyAsync(dummy -> {
ClassD resultClass = new ClassD();
ClassA classA = classAFuture.join();
if (classA != null) {
resultClass.setClassA(classA);
}
ClassB classB = classBFuture.join();
if (classB != null) {
resultClass.setClassB(classB);
}
ClassC classC = classCFuture.join();
if (classC != null) {
resultClass.setClassC(classC);
}
return resultClass;
});
}
Run Code Online (Sandbox Code Playgroud)
现在,调用者getResultClassD()可以使用返回CompletableFuture来查询进度状态或链依赖操作,或者join()在操作完成后用于检索结果.
为解决其他问题,是的,此操作是异步的,并且join()在lambda表达式中使用是合适的.join是完全创建的,因为Future.get(),声明抛出已检查的异常,使得在这些lambda表达式中的使用不必要地变硬.
请注意,null测试仅在service.getClassX()实际返回时才有用null.如果其中一个服务调用因异常而失败,则整个操作(由表示CompletableFuture<ClassD>)将异常完成.
我走的路线与@Holger 在他的回答中所做的类似,但将服务调用包装在一个可选中,这会导致 thenApplyAsync 阶段中的代码更清晰
CompletableFuture<Optional<ClassA>> classAFuture
= CompletableFuture.supplyAsync(() -> Optional.ofNullable(service.getClassA())));
CompletableFuture<Optional<ClassB>> classBFuture
= CompletableFuture.supplyAsync(() -> Optional.ofNullable(service.getClassB()));
CompletableFuture<Optional<ClassC>> classCFuture
= CompletableFuture.supplyAsync(() -> Optional.ofNullable(service.getClassC()));
return CompletableFuture.allOf(classAFuture, classBFuture, classCFuture)
.thenApplyAsync(dummy -> {
ClassD resultClass = new ClassD();
classAFuture.join().ifPresent(resultClass::setClassA)
classBFuture.join().ifPresent(resultClass::setClassB)
classCFuture.join().ifPresent(resultClass::setClassC)
return resultClass;
});
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3079 次 |
| 最近记录: |