java - 在可完成的 future 之内/之后抛出异常

标签 java asynchronous exception java-8 completable-future

我有一个这样的可完成 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/

相关文章:

c++ - 等待互斥锁时的进程

c# - 异常(exception) - 最佳实践

Java EE 容器内部结构

Java:将固定大小的字节数组转换为可变长度的字符串

javascript - 异步加载 NPM 模块

c# - 为什么编译器检测不到这里会抛出异常呢?

c++ - 如何检测异常何时发生?

java - 保留数组中的默认值?

java - 应用程序未在启动时启动

ios - 异步等待失败的 swift API 请求