This is Part 1 of Future vs. CompletableFuture. In this blog we will be comparing Java 5’s Future with Java 8’s CompletableFuture on the basis of two categories i.e. manual completion and attaching a callable method.

What is 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.

CompletableFuture implements two interfaces:

  1. Future
  2. CompletionStage

Future vs. CompletableFuture

1. Manual Completion

Talking about manual completition , future 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. But if there comes a scenario where you need to complete it manually, Future does not provides any means to do so.

But in Java 8’s completableFuture, CompletableFuture.complete() method helps us to manually complete a Future. Let’s have a look at an example to see it in more detail.

Creating a CompletableFuture simple by having a no-arg constructor.

CompletableFuture completableFuture = new CompletableFuture();

To fetch the result, you can use get() method.


String result = completableFuture.get();

 Since we know that get() method blocks until the future is complete, the above call will block forever since the future is never completed. Therefore, we can use complete() method in order to manually complete the result.


completableFuture.complete("Welcome to Knoldus!");

2. Attaching a callable method

While using Future, we do not get notified when it is complete neither does it provides us a callable method which will automatically be called when the result is available but CompletableFuture provides us with a lot of callable methods which can be used as per our use case. But before we go through callable methods let’s have a basic understanding of runAsync() and supplyAsync() for asynchronous computation.

a) runAsync()

It is used for running some background task asynchronously but not returning anything by using a Runnable instance. It takes a Runnable object and returns CompletableFuture. For example:

        CompletableFuture future = CompletableFuture.runAsync(() -> {
            try {
                System.out.println("Running asynchronous task in parallel");
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException ex) {
                throw new IllegalStateException(ex);
            }
        });

In the above example, we have used lambda expression for passing Runnable object.

b) supplyAsync()

This method is used when you want to return some value from the background task running asynchronously. It takes a Supplier and returns CompletableFuture. Here, Supplier is a functional interface and T is the type of value returned from the supplier. For example:

        CompletableFuture future = CompletableFuture.supplyAsync(() -> {
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                throw new IllegalStateException(e);
            }
            return "This is the result of the asynchronous computation";
        });

Note: Async methods are used to run the task on a separate thread apart from the main thread whereas the methods without the Async postfix run the execution stage using a calling thread. When using methods with Async postfix, you can specify the executor as second argument.  By default it is ForkJoinPool.commonPool() method that is used.

Now, let’s have a look at each of the callable method:

i) thenApply()

It takes a Function as an argument. Function is a functional interface which represents a function that it takes argument of type T and returns argument of type R.

CompletableFuture completableFuture = CompletableFuture.supplyAsync(() -> {
   try {
       TimeUnit.SECONDS.sleep(1);
   } catch (InterruptedException e) {
       throw new IllegalStateException(e);
   }
   return "Knolders!";
});
CompletableFuture result = completableFuture.thenApply(name -> "Hello " + name);

We can even apply a sequence of transformations using thenApply() where the result of 1st thenApply() is passed to the 2nd thenApply() and so on. For example:

CompletableFuture result = CompletableFuture.supplyAsync(() -> {
   try {
       TimeUnit.SECONDS.sleep(1);
   } catch (InterruptedException e) {
       throw new IllegalStateException(e);
   }
   return "Knolders!";
}).thenApply(name -> "Hello " + name)
  .thenApply(greeting -> greeting + " Welcome to Knoldus Inc!");

ii) thenAccept()

It takes a Consumer and returns CompletableFuture. It has access to the result of the CompletableFuture on which it is attached. For example:

        CompletableFuture completableFuture = CompletableFuture.supplyAsync(() -> "Knolders!");
        CompletableFuture result
                = completableFuture.thenAccept(value -> System.out.println("Hello " + value));

iii) thenRun()

It also takes a Consumer and returns CompletableFuture. If you neither need the value of the computation nor want to return some value at the end of the chain, then you can pass a Runnable lambda to the thenRun() method. Hence, in this case we do not have access to future’s result.

For example:

        CompletableFuture completableFuture
                = CompletableFuture.supplyAsync(() -> "Knolders!");
        CompletableFuture result
                = completableFuture.thenRun(() -> System.out.println("Example with thenRun()."));

Note:

  • While processing results of asynchronous computations, we also have callable methods with async variants where we can specify the executor as discussed above.
  • The consumer methods are often used as the last callback in the callback chain.

Upcomings

In the next blog, I will be comparing Future with CompletableFuture on the basis of

  • Combining 2 CompletableFutures together
  • Combining multiple CompletableFutures together
  • Exception Handling

References


knoldus-advt-sticker


One comment

Leave a Reply

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

WordPress.com Logo

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

Google+ photo

You are commenting using your Google+ 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 )

w

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.