Skip to content
Advertisement

Why does calling CompletableFuture::cancel cause an immediate CancellationException

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.

Advertisement

Answer

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)
User contributions licensed under: CC BY-SA
5 People found this is helpful
Advertisement