Press "Enter" to skip to content

CompletableFuture Timeouts in Java

As far as I love Java 8’s CompletableFuture, it has its downsides – idiomatic handling of timeouts is one of them.

Luckily, JDK 9 brought two new methods that provide the functionality everyone longed for – which is crucial for ensuring the proper resiliency when working with asynchronous processing.

In this super-short article, I will try to raise the awareness of the new crucial API methods.


Simply put, after calling the above method. The future will throw an ExecutionException if it doesn’t complete within a specified timeout.

A simple example:

CompletableFuture<Integer> future = CompletableFuture.supplyAsync(this::computeEndlessly)
  .orTimeout(1, TimeUnit.SECONDS);

future.get(); // java.util.concurrent.ExecutionException after waiting for 1 second


In this option, we can return a default value once the timeout is reached:

CompletableFuture<Integer> future = CompletableFuture.supplyAsync(this::computeEndlessly)
  .completeOnTimeout(42, 1, TimeUnit.SECONDS);

Integer result = future.get(); // 42

As simple as that, although I don’t necessarily like the fact that we’re always forced to precompute the default value. If you look at the signature, you will see, that the value isn’t computed lazily:

public CompletableFuture<T> completeOnTimeout(T value, long timeout, TimeUnit unit)

This could’ve been easily achieved, for example, by providing an alternative API method that accepted Supplier<T> instead of plain Tmore about the idea can be found here.


The complete example can be found on GitHub.

If you enjoyed the content, consider supporting the site:

Support the siteSupport the site