为什么调用 CompletableFuture::cancel 会立即导致 CancellationException

Why does calling CompletableFuture::cancel cause an immediate CancellationException

我想在 CompletableFuture 上给 cancel 打电话。

从文档看来:

If not already completed, completes this CompletableFuture with a CancellationException. Dependent CompletableFutures that have not already completed will also complete exceptionally, with a CompletionException caused by this CancellationException.

它应该异常完成它们,这是我所期待的,但相反,它抛出并立即取消异常。

这是一个示例代码

CompletableFuture<?> f = CompletableFuture.supplyAsync(() -> false);
f.cancel(true);  // Line 7.
f.join();

有了复现:https://www.mycompiler.io/view/2v1ME4u

Exception in thread "main" java.util.concurrent.CancellationException
    at java.base/java.util.concurrent.CompletableFuture.cancel(CompletableFuture.java:2396)
    at Main.main(Main.java:7)

第 7 行是 f.cancel(true); 行。

它实际上并没有立即抛出。

调用 f.cancel(true) 会导致 创建 CancellationException,捕获调用 cancel 的堆栈跟踪。因此堆栈跟踪(由于未处理而被打印出来)包含 f.cancel(true); 调用的行。

但是直到 f.join():

才真正抛出该异常

Returns the result value when complete, or throws an (unchecked) exception if completed exceptionally

...

Throws:

CancellationException - if the computation was cancelled

你可以通过再输入几个打印语句来看到这一点 into your example code:

CompletableFuture<?> f = CompletableFuture.supplyAsync(() -> false);
f.cancel(true);  // Line 8.
try {
    f.join();
} catch (CancellationException e) {
    System.out.println("CancellationException was thrown at call to f.join()");
    e.printStackTrace(System.out);
}

输出:

CancellationException was thrown at call to f.join()
java.util.concurrent.CancellationException
    at java.base/java.util.concurrent.CompletableFuture.cancel(CompletableFuture.java:2396)
    at Main.main(Main.java:8)