我有一个可完成的期货列表,我想从第一个期货开始,如果有任何完成异常,我想尝试列表中的下一个期货,以此类推,直到我用完所有的期货。如果任何一个期货成功,我想停止在那里,而不使用列表中的下一个期货。我怎样才能实现这个目标呢?到目前为止,我已经尝试过这个方法。
for (SampleFutures future : getSampleFutures()) {
try {
return future.someMethod();
} catch (Exception e) {
log.error("An exception occurred, Will try the next future.", e);
}
}
但是当我测试这个方法的时候,我看到当有什么东西失败的时候 未来完成的异常就会被抛出,下一组期货就不会被尝试。
编辑。
这就是SampleFtures的样子
public class SampleFutureA implements SampleFutures {
@Override
public CompletableFuture<SomeOject> someMethod() {
return CompletableFuture
.supplyAsync(() -> someOtherMethod())
.thenApply( ()->anotherMethod())
.exceptionally(ex -> exceptionHandler(ex));
}
对于这种问题,我建议使用 EA异步 因为它提供了一种asyncawait的机制,使得它很容易实现。
当你的应用程序启动时,初始化async(你也可以对应用程序进行预处理,读到的是 文件 详见)
Async.init();
然后用 await()
如下所示。
for (SampleFutures future : getSampleFutures()) {
try {
return completedFuture(await(future.someMethod()));
} catch (Exception e) {
log.error("An exception occurred, Will try the next future.", e);
}
}
throw new RuntimeException("All futures failed!");
但是,如果你不能或不想使用它,你可以用一个递归异步方法来实现同样的事情。
private CompletableFuture<SomeObject> processNext(Iterator<SampleFutures> iterator) {
if (iterator.hasNext()) {
return iterator.next().someMethod()
.handle((r, e) -> {
if (e != null) {
log.error("An exception occurred, Will try the next future.", e);
return processNext(iterator);
} else {
return completedFuture(r);
}
}).thenCompose(c -> c);
}
CompletableFuture<SomeObject> allFailed = new CompletableFuture<>();
allFailed.completeExceptionally(new RuntimeException("All futures failed!"));
return allFailed;
}
你可以用一个递归的异步方法来实现同样的事情
return processNext(getSampleFutures().iterator());
这个方法会调用第一个未来,只有当它失败的时候,它才会递归地调用自己的异步,从而调用下一个。
不幸的是,我们不得不用 hande()
+ thenCompose(c -> c)
因为没有 "compose "版本的 handle()
和 exceptionally()
. 所以... handle()
返回一个 CompletableFuture<CompletableFuture<SampleObject>>
和 thenCompose()
只是解开它。