我有一个这样的可完成 future 列表:
List<CompletableFuture<MyObject>> futures = class_list.stream()
.map(c -> CompletableFuture.supplyAsync(() ->
try {
return helper(c);
} catch (Throwable th) {
throw th; // doesn't work
}
))
.exceptionally(ex -> {
throw ex; // also didn't work
}
然后我遍历我的 futures 并尝试再次抛出异常:
futures.stream.map(f -> {
try {
return f.get();
}catch(Completionexception ex){
throw new ex; (also didn't work)
}
理想情况下,我希望在发现可抛出的异常时退出整个异步过程。
最佳答案
不需要像
这样的结构try {
return helper(c);
}catch(Throwable th) {
throw th;
}
因为捕获并重新抛出异常的行为与首先不捕获异常没有什么不同。同样,如果合法,链接 .exceptionally(ex -> { throw ex; }
将毫无意义。(事实并非如此,因为 Throwable
是一个已检查的异常。
如果 helper 不抛出已检查的异常,您可以简单地使用 CompletableFuture.supplyAsync(() -> helper(c))
。否则,您必须将已检查的异常包装到未检查的异常中;这里最自然的选择是 CompletionException
。
这看起来像:
List<CompletableFuture<MyObject>> futures = class_list.stream()
.map(c -> CompletableFuture.supplyAsync(() ->
try {
return helper(c);
} catch(Throwable th) {
throw new CompletionException(th);
}
))
.collect(Collectors.toList());
你的第二个操作很草率。类名是 CompletionException
,而不是 Completionexception
。此外,抛出存储在变量 ex
中的现有异常是通过 throw ex;
而不是 throw new ex;
完成的。但如前所述,当您希望(重新)抛出异常时,首先不要捕获它。
问题是 get
抛出已检查的 ExecutionException
而不是未检查的 CompletionException
。对于后者,您必须使用 join
。所以你可以通过
// will throw when any future completed exceptionally
futures.forEach(CompletableFuture::join);
关于java - 在可完成的 future 之内/之后抛出异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58662840/