Future vs CompletableFuture
In this article, we will cover the significant differences between Future and Completable Future. But, before we see the differences, let's first talk about what these two are, and then let us see an example of how we can implement them.
What is Future?
Future is an interface in Java introduced in Java 5 and it's mostly being used to create asynchronous tasks. Now, why there is a need to create asynchronous tasks? Let us assume that we are creating a website where we have to do some computation in order which means we have to complete Task-1 before Task-2. With synchronous tasks, our web application will wait for Task-1 to be completed before proceeding to Task-2 where the application could be something else during this wait time.
In asynchronous design, our application will continue working on tasks that are not dependent on Task-1 to be completed and that's why there is a need for asynchronous architecture.
Code Example-
import java.util.concurrent.*; public class FutureDemo { public static void main(String[] args) throws ExecutionException, InterruptedException { Future<String> futureObj = Executors.newSingleThreadExecutor().submit(() -> { TimeUnit.SECONDS.sleep(2); return "Hello World!"; }); while (!futureObj.isDone()) { System.out.println("Result hasn't yet returned"); } System.out.println("Result -> " + futureObj.get()); } }
Drawbacks with Future
- Future can't be finished explicitly.
- Without blocking, we can't do anything else with a Future's result.
- There is no way to execute multiple Futures in simultaneously and then combine the results.
- There are no exception handling constructs in the Future.
What is CompletableFuture?
CompletableFuture is an class in Java introduced in Java 8 and as you might have guessed this class implements Future interface. Now, why do we use CompletableFuture? That's the big question, right? CompletableFuture was a significant improvement over Future interface. Let's understand this better.
With Future, we had a lot of difficulties like we can't combine results which is what we saw above in drawbacks of Future also. CompletableFuture implements CompletionStage interface through which we can combine the results with other steps. Just like this, CompletableFuture came with around 60 methods just to provide a better functionality for asynchronous computation.
Now, let's see some working examples.
Code Example1-
import java.util.concurrent.*; public class CompletableFutureDemo1 { public static void main(String[] args) throws ExecutionException, InterruptedException { CompletableFuture<String> futureObj = new CompletableFuture<>(); Executors.newSingleThreadExecutor().submit(() -> { try { TimeUnit.SECONDS.sleep(2); } catch (InterruptedException e) { e.printStackTrace(); } futureObj.complete("Hello World"); }); while (!futureObj.isDone()) { System.out.println("Result hasn't yet returned"); } System.out.println("Result -> " + futureObj.get()); } }
Code Example2-
import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; public class CompletableFutureDemo2 { public static void main(String[] args) throws ExecutionException, InterruptedException { CompletableFuture<String> completableFutureResultObj1 = CompletableFuture.supplyAsync(() -> "Hello").thenApply(hello -> hello + "World"); CompletableFuture<String> completableFutureResultObj2 = getHello().thenCompose(hello -> getHelloWorld(hello)); System.out.println(completableFutureResultObj1.get()); System.out.println(completableFutureResultObj2.get()); } private static CompletableFuture<String> getHello() { return CompletableFuture.supplyAsync(() -> "Hello"); } private static CompletableFuture<String> getHelloWorld(String hello) { return CompletableFuture.supplyAsync(() -> hello + " World"); } }
No comments:
Post a Comment