Java 8 CompletableFuture 异常方法的惊人行为
Posted
技术标签:
【中文标题】Java 8 CompletableFuture 异常方法的惊人行为【英文标题】:Surprising behavior of Java 8 CompletableFuture exceptionally method 【发布时间】:2015-02-10 08:58:28 【问题描述】:我遇到了 Java 8 CompletableFuture.exceptionally 方法的奇怪行为。如果我执行此代码,它可以正常工作并打印java.lang.RuntimeException
CompletableFuture<String> future = new CompletableFuture<>();
future.completeExceptionally(new RuntimeException());
future.exceptionally(e ->
System.out.println(e.getClass());
return null;
);
但是如果我在以后的处理中添加另一个步骤,例如thenApply
,异常类型将更改为java.util.concurrent.CompletionException
,其中包含原始异常。
CompletableFuture<String> future = new CompletableFuture<>();
future.completeExceptionally(new RuntimeException());
future.thenApply(v-> v).exceptionally(e ->
System.out.println(e);
return null;
);
有什么理由会发生这种情况吗?在我看来,这很令人惊讶。
【问题讨论】:
查看 ***.com/q/49230980/14731 了解何时包装(或不包装)异常的概述。 这是我发现的一篇文章,帮助我更好地理解了这个问题的解决方案 -> millross-consultants.com/… @The0bserver,您添加的链接信息量很大,虽然不是全部,但我的很多疑问都清楚了:) 很高兴我能帮上忙@NIGAGA。 【参考方案1】:这种行为is specified in the class documentation of CompletionStage
(fourth bullet):
方法
handle
还允许该阶段计算替换结果,该结果可能允许其他相关阶段进行进一步处理。在所有其他情况下,如果某个阶段的计算因(未经检查的)异常或错误而突然终止,则所有需要其完成的相关阶段也会异常完成,CompletionException
将异常作为其原因。
如果您考虑到您可能想知道您调用 exceptionally
的阶段是否失败,或者它的直接或间接先决条件之一是否失败,这并不奇怪。
【讨论】:
【参考方案2】:是的,该行为是预期的,但如果您想要从先前阶段之一抛出的原始异常,您可以简单地使用它
CompletableFuture<String> future = new CompletableFuture<>();
future.completeExceptionally(new RuntimeException());
future.thenApply(v-> v).exceptionally(e ->
System.out.println(e.getCause()); // returns a throwable back
return null;
);
【讨论】:
以上是关于Java 8 CompletableFuture 异常方法的惊人行为的主要内容,如果未能解决你的问题,请参考以下文章
Java 8 CompletableFuture 与 Netty 未来
Java 8 的异步编程利器 CompletableFuture 详解
Java 8 的异步编程利器 CompletableFuture 详解