为什么Java 8 CompletableFuture thenCompose会根据完成顺序生成不同的异常?

时间:2015-01-02 20:11:23

标签: java java-8 future

我遇到过Java 8 CompletableFuture thenCompose方法的奇怪行为。我有两个测试,仅在执行顺序上有所不同。两个测试都模拟了thenCompose中生成的CompletableFuture中的失败。

@Test
public void completedAfter() {
    CompletableFuture<String> future1 = new CompletableFuture<>();
    CompletableFuture<String> future2 = new CompletableFuture<>();

    future1.thenCompose(x -> future2).whenComplete((r, e) -> System.out.println("After: " + e));

    future1.complete("value");
    future2.completeExceptionally(new RuntimeException());
}

@Test
public void completedBefore() {
    CompletableFuture<String> future1 = new CompletableFuture<>();
    CompletableFuture<String> future2 = new CompletableFuture<>();

    future1.complete("value");
    future2.completeExceptionally(new RuntimeException());

    future1.thenCompose(x -> future2).whenComplete((r, e) -> System.out.println("Before: " +e));
}

输出结果为:

After: java.util.concurrent.CompletionException: java.lang.RuntimeException
Before: java.lang.RuntimeException

问题是,为什么在一个案例中CompletionException包含异常但在另一个案例中却没有?

更新:Here是相关的错误报告。它已被标记并解析为JDK中的错误。

1 个答案:

答案 0 :(得分:2)

似乎是jdk库中的一个错误。

在“After”案例中,.thenComposeThenCopy完成节点添加到目标将来,其执行稍后由.completeExceptionally触发。完成节点的run方法在将来查找异常,并在目标上调用.internalComplete,将所有异常包装到CompletionException。 请参阅here节点的创建方式,以及here包装发生的位置。

现在,在Before的情况下,代码路径完全不同。由于未来已经完成,.thenCompose不会创建其他节点,而是立即invokes回调,只返回(已完成的第二个未来),然后调用.whenComplete ,再次,并不打算创建一个新的完成节点,而只是立即invokes the callback,从第二个未来给它原始的例外。

男孩,看看这段代码,有很多例子我想向学生展示他们应该做的事情......