Java - How to use Futures

A Future is a class that represents the result of an asynchronous operation. Future can be used to pass some data processed in a multi-threaded environment to another thread.

Because Future is implemented to be thread-safe internally, there is no need to use synchronized block.

An example makes it easier to understand.

Simple Future Example

In the example below, two Threads are created, and data processed in one thread is transferred to another thread using Future.

ExecutorService executor
        = Executors.newSingleThreadExecutor();

Future<Integer> future = executor.submit(() -> {
    System.out.println(LocalTime.now() + " Starting runnable");
    Integer sum = 1 + 1;
    Thread.sleep(3000);
    return sum;
});

System.out.println(LocalTime.now() + " Waiting the task done");
Integer result = future.get();
System.out.println(LocalTime.now() + " Result : " + result);
  • ExecutorService creates a single thread. If a Callable is passed to submit(), the Callable passed as an argument is executed.
  • A Future object is returned when executor.submit() is called. but the value is not set yet
  • future.get() waits for some value to be set in the Future object. If the Callable passed to submit() returns a value, that value is set in the Future.

Callable is an interface that takes no arguments but returns some data. Runnable is an interface that takes no arguments and returns no data.

The execution result is as follows.

01:18:18.347 Starting runnable
01:18:18.347 Waiting the task done
01:18:21.348 Result : 2

Another Future example

The example above is simple, but it doesn`t show how the Future is created and how the data is stored.

You can check these parts by looking at the following example.

CompletableFuture<Integer> future
        = new CompletableFuture<>();

Executors.newCachedThreadPool().submit(() -> {
    System.out.println(LocalTime.now() + " Doing something");
    Integer sum = 1 + 1;
    Thread.sleep(3000);
    future.complete(sum);
    return null;
});

System.out.println(LocalTime.now() + " Waiting the task done");
Integer result = future.get();
System.out.println(LocalTime.now() + " Result : " + result);
  • CompletableFuture<Integer> to create a Future object. It is implemented as Generics and specifies the data type to be saved.
  • Executors.newCachedThreadPool() creates a thread pool, and if you pass a callable to submit(), it is executed from the waiting thread
  • Save data to pass to another thread with future.complete(data)
  • Wait for data to be set with future.get()

The execution result is as follows.

01:23:54.929 Doing something
01:23:54.929 Waiting the task done
01:23:57.930 Result : 2

Set Timeout to Future.get()

If data is not set in Future, the thread that called Future.get() waits indefinitely. Then the program becomes unresponsive.

You can set a Timeout in Future.get() to return if there is no response within a certain amount of time to handle the next operation.

To set Timeout, pass timeout and TimeUnit, the unit of time, together to get() as shown below.

Future.get(long timeout, TimeUnit unit)

The following is an example of applying Timeout.

ExecutorService executor
        = Executors.newSingleThreadExecutor();

Future<Integer> future = executor.submit(() -> {
    System.out.println(LocalTime.now() + " Starting runnable");
    Integer sum = 1 + 1;
    Thread.sleep(4000);
    System.out.println(LocalTime.now() + " Exiting runnable");
    return sum;
});

System.out.println(LocalTime.now() + " Waiting the task done");
Integer result = null;
try {
    result = future.get(2000, TimeUnit.MILLISECONDS);
} catch (TimeoutException e) {
    System.out.println(LocalTime.now() + " Timed out");
    result = 0;
}
System.out.println(LocalTime.now() + " Result : " + result);
  • get(2000, TimeUnit.MILLISECONDS) means set 2000ms to Timeout. You can also change TimeUnit to SECONDS etc.
  • If a timeout occurs, a TimeoutException exception is thrown. Exception handling is required with try-catch

The execution result of the above code is as follows.

11:55:06.693 Waiting the task done
11:55:06.693 Starting runnable
11:55:08.696 Timed out
11:55:08.696 Result : 0
11:55:10.696 Exiting runnable
codechachaCopyright ©2019 codechacha