Java 8  - Future vs CompletableFuture

Java 8 - Future vs CompletableFuture

CompletableFuture is used for asynchronous programming in Java. Asynchronous programming is a means of writing non-blocking code by running a task on a separate thread than the main application thread and notifying the main thread about its progress, completion or failure.

This way, your main thread does not block/wait for the completion of the task and it can execute other tasks in parallel.Having this kind of parallelism greatly improves the performance of your programs.

  • CompletableFuture is an extension to Java’s Future API which was introduced in Java
  • A Future is used as a reference to the result of an asynchronous computation. It provides an isDone() method to check whether the computation is done or not, and a get() method to retrieve the result of the computation when it is done.
  • You can learn more about Future from my Callable and Future Tutorial.
  • Future API was a good step towards asynchronous programming in Java but it lacked some important and useful features

Limitations of Future

  • It can not be manually completed

Let’s say that you’ve written a function to fetch the latest price of an e-commerce product from a remote API. Since, this API call is time consuming, you’re running it in a separate thread and returning a Future from your function.Now, let’s say that If the remote API service is down, then you want to complete the Future manually by the last cached price of the product.

  • Can you do this with Future? No!

You can not perform further action on a Future’s result without blocking Future does not notify you about its completion. It provides a get() method which blocks until the result is available.

You don’t have the ability to attach a callback function to the Future and have it get called automatically when the Future’s result is available.

  • Multiple Futures can not be chained together

Sometimes you need to execute a long running computation and when the computation is done, you need to send its result to another long running computation, and so on.

  • You can not create such asynchronous work flow with Futures.
  • You can not combine multiple Futures together

Let’s say that you have 10 different Futures that you want to run in parallel and then run some function after all of them completes. You can’t do this as well with Future.

  • No Exception Handling

Future API does not have any exception handling construct.Whoa! So many limitations right? Well, That’s why we have CompletableFuture. You can achieve all of the above with CompletableFuture.

CompletableFuture implements Future and CompletionStage interfaces and provides a huge set of convenience methods for creating, chaining and combining multiple Futures. It also has a very comprehensive exception handling support.

Creating a CompletableFuture :-

You can create a CompletableFuture simply by using the following no-arg constructor -

CompletableFuture<String> completableFuture = new CompletableFuture<String>();

This is the simplest CompletableFuture that you can have. All the clients who want to get the result of this CompletableFuture can call CompletableFuture.get() method -

String result = completableFuture.get()

The get() method blocks until the Future is complete. So, the above call will block forever because the Future is never completed.

You can use CompletableFuture.complete() method to manually complete a Future -

completableFuture.complete("Future's Result")

All the clients waiting for this Future will get the specified result. And, Subsequent calls to completableFuture.complete() will be ignored.

 Running asynchronous computation using runAsync()

If you want to run some background task asynchronously and don’t want to return anything from the task, then you can use CompletableFuture.runAsync() method. It takes a Runnable object and returns CompletableFuture<Void>.

Running a task asynchronously and return the result using supplyAsync() 

CompletableFuture.runAsync() is useful for tasks that don’t return anything. But what if you want to return some result from your background task?

Well, CompletableFuture.supplyAsync() is your companion. It takes a Supplier<T> and returns CompletableFuture<T> where T is the type of the value obtained by calling the given supplier

A Supplier<T> is a simple functional interface which represents a supplier of results. It has a single get() method where you can write your background task and return the result

To view or add a comment, sign in

More articles by 🧿 Saral Saxena

Others also viewed

Explore content categories