Java 8 CompletableFuture intro

25 09 2015

CompletableFuture is Java’s 8 abstraction for async tasks in event driven programming. It s designated for executing long running operations (http requests, database queries, file operations or complicated computations).

CompletableFuture seems to be very legit response for the need addressed by Guava’s ListenableFuture (see my intro here).

How it works

The idea behind is as follows:

  1. create CompletableFuture object by a static method
  2. provide the task to be executed asynchronously
  3. wait for the callback until the task execution is complete
    1. There are few variations of waiting for callback – I’ll show them later in this post

Get the source code

Source code for this demo is on my github:

The basic demo

My long running task sleeps thread for 5 seconds. The execution is concurrent so the task is sleeping, but the main execution continues.

Construct the CompletableFuture with task

The CompletableFuture declaration consists of static method to provide the function that represents long running task with lambda expression:

CompletableFuture future = CompletableFuture.supplyAsync(() -> {
    log("Starting task in CompletableFuture");
    String completionTime = executeLongRunningProcess();
    log("Future task completed at: " + completionTime);
    return completionTime;

The long running task is just sleep(5000) and some log messages:

private static String executeLongRunningProcess() {
    try {
    } catch (InterruptedException e) {
        return "Exception: " + e.getMessage();

Getting the future computation results

The simplest way is to call get() on CompletableFuture object:

String result = (String) future.get();

Until now the main thread execution was not blocked by the long running process and you could execute other methods. Now when you execute get():

  • if the future has completed, you will get the result
  • if task is not completed yet, the main thread will wait for completion (success or failure)

Since my task takes 5 seconds to complete my main thread needs to wait. This is the log:

21:51:31.580: Starting the demo
21:51:31.990: Continuing main thread execution
21:51:31.993: Starting task in CompletableFuture
21:51:36.994: Future task completed at: 21:51:36.994
21:51:36.994: Future get result is: 21:51:36.994

Note here that the main thread was continuing its execution until the get() method that blocked it. After future have completed, the execution was resumed.

This will wait forever until the future completion or failure. But what if you want the result NOW?

Get future result now or provide the fallback value

If you require to have the future task result at the time of get() execution you need to remember that task may not have yet completed. If so, you may leave it executing not caring about its result now. Then just provide the fallback value and continue main thread execution with getNow(valueIfAbsent):

String result = (String) future.getNow("Task not yet completed");

now the main thread will not wait for the Future to complete:

22:02:37.170: Starting the demo
22:02:37.605: Continuing main thread execution
22:02:37.605: Starting task in CompletableFuture
22:02:38.605: Future get result is: Task not yet completed

Wait for the certain amount of time
In this case you can declare that you wait for task to complete for 3 seconds. If it is complete, you get the value and proceed, else the TimeoutException is thrown. Use the get(long amount, TimeUnit unit):

String result = (String) future.get(3, TimeUnit.SECONDS);

Since the task takes 5 seconds to complete, the exception is thrown:

22:07:28.728: Starting the demo
22:07:29.125: Continuing main thread execution
22:07:29.126: Starting task in CompletableFuture
Exception in thread "main" java.util.concurrent.TimeoutException
	at java.util.concurrent.CompletableFuture.timedAwaitDone(
	at java.util.concurrent.CompletableFuture.get(
	at com.looksok.future.Main.main(
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(
	at java.lang.reflect.Method.invoke(
	at com.intellij.rt.execution.application.AppMain.main(

What more can be done

When you dive deeper into the Futures you will use concepts like joining, combining etc. As for now this should be enough.

Get the source code

Source code for this demo is on my github:



Give Your feedback:

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: