Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What happens when the response from the CompletableFuture is ignored?

I am experimenting with CompletableFuture in making async API calls. I am trying to understand the implication of ignoring the response from a Future. The JVM technically executes the async API call and returns the result.

But in case we have no CompletableFuture.get() call to retrieve the response, I assume that the response is never being accessed in the code. From an operational standpoint, is that something safe? Are there any specific caveats/safety checks which I should be aware of when I ignore the response from the CompletableFuture?

like image 854
chrisrhyno2003 Avatar asked Oct 15 '25 13:10

chrisrhyno2003


1 Answers

There is no tight relationship between the scheduled task and the CompletableFuture. Your task will be wrapped in a job which will do the following things

  1. Check whether the CompletableFuture has not completed yet. If not, continue with
  2. Execute the task
  3. Try to complete the CompletableFuture with the result

This processing does not depend on invocations of get() or join() nor whether you chained any dependent actions. Further, once the evaluation of the task has started, it even doesn’t matter whether you call cancel or complete on the future, the evaluation will continue and only the final completion attempt of the last step will not do anything when the future has already been completed.

In other words, the logic of, e.g. runAsync, is similar to

public static CompletableFuture<Void> runAsync(Runnable r) {
    CompletableFuture<Void> future = new CompletableFuture<>();
    ForkJoinPool.commonPool().execute(
        (Runnable&CompletableFuture.AsynchronousCompletionTask)() -> {
            if(!future.isDone()) try {
                r.run();
                future.complete(null);
            }
            catch(Throwable t) {
                future.completeExceptionally(t);
            }
        });
    return future;
}

The CompletableFuture instance is just an object. If you don’t keep a reference to it, the code attempting the completion will have one until the attempt was made.

Note that the default executor, the ForkJoinPool.commonPool(), uses daemon threads. So when you submit tasks in the main thread without waiting for their completion and no non-daemon thread is left in the JVM, it will terminate without waiting for the completion at all. If these tasks perform actions visible to the outside world, e.g. writing to a file, you likely want to ensure their completion, so may invoke awaitQuiescence to ensure that no background task is running before shutting down the JVM.

like image 80
Holger Avatar answered Oct 18 '25 02:10

Holger