I am trying to call cancel
on CompletableFuture
.
It seems from the docs:
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.
That it should complete them exceptionally which is what I was expecting but instead, it throws and immediate CancellationException.
Here is a sample code
CompletableFuture<?> f = CompletableFuture.supplyAsync(() -> false);
f.cancel(true); // Line 7.
f.join();
With a repro : 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)
Line 7 is the f.cancel(true);
line.
It doesn't actually throw immediately.
Calling f.cancel(true)
causes a CancellationException
to be created, capturing the stack trace of the call to cancel
. So the stack trace (which is printed because it's unhandled) contains the line of the f.cancel(true);
call.
But that exception isn't actually thrown until f.join()
:
Returns the result value when complete, or throws an (unchecked) exception if completed exceptionally
...
Throws:
CancellationException - if the computation was cancelled
You can see this by putting in a few more print statements 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);
}
Output:
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)