这是MCVE:
public static void main(String[] args) {
CompletableFuture<String> r1 = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
return "41";
});
CompletableFuture<String> r2 = CompletableFuture.supplyAsync(() -> "42");
CompletableFuture<String> r3 = CompletableFuture.supplyAsync(() -> {
System.out.println("I'm called.");
return "43";
});
CompletableFuture.allOf(r1, r2, r3).thenRun(() -> { System.out.println("End."); });
Stream.of(r1, r2, r3).forEach(System.out::println);
}
有点奇怪,没有真正完成CompletableFuture
from allOf(...)
,例如调用 its join()
,我得到以下输出:
I'm called.
java.util.concurrent.CompletableFuture@<...>[Not completed, 1 dependents]
java.util.concurrent.CompletableFuture@<...>[Completed normally]
java.util.concurrent.CompletableFuture@<...>[Completed normally]
我可以知道是什么导致 JVM 处理/认为r1
有1 个(估计数量)依赖CompletableFuture
,而它决定直接完成r2
和r3
?我能看到的唯一区别就是try-catch
,那么答案就这么简单吗?
作为比较,当我join()
最后实际执行 a 时,我得到了 5 秒的预期等待时间和以下输出。如果有帮助,我会在 Java 8 Update 40 JVM 上遇到这个问题。
修改:
// ...
CompletableFuture.allOf(r1, r2, r3).thenRun(() -> { System.out.println("End."); }).join();
Stream.of(r1, r2, r3).forEach(System.out::println);
输出:
I'm called.
// <note: 5-second wait is here>
End.
java.util.concurrent.CompletableFuture@<...>[Completed normally]
java.util.concurrent.CompletableFuture@<...>[Completed normally]
java.util.concurrent.CompletableFuture@<...>[Completed normally]