Java 8 - CompletableFuture
Java 8 introduced a powerful new feature called CompletableFuture, which is a powerful tool for performing asynchronous operations. In this blog, we will explore what CompletableFuture is, how it works, and how you can use it to write more efficient and scalable code.
What is CompletableFuture?
CompletableFuture is a class in Java 8 that represents a future result of an asynchronous operation. A CompletableFuture object can be completed with a result value, an exception, or even another CompletableFuture object, which can be used to chain multiple asynchronous operations.
CompletableFuture provides a powerful API for performing asynchronous operations, with methods that support chaining and composition of operations, error handling, and timeouts.
Creating a CompletableFuture
There are several ways to create a CompletableFuture object. One of the simplest is to use the CompletableFuture.supplyAsync() method, which takes a Supplier function that returns a value.
1
CompletableFuture<String> completableFuture = CompletableFuture.supplyAsync(() -> "Hello, world!");
Chaining CompletableFuture
One of the most powerful features of CompletableFuture is the ability to chain multiple asynchronous operations. You can chain CompletableFuture objects using the thenApply() method, which takes a Function that maps the result of the first CompletableFuture to a new value.
1
2
3
CompletableFuture<String> completableFuture = CompletableFuture.supplyAsync(() -> "Hello, world!")
.thenApply(s -> s + " from CompletableFuture");
You can also chain CompletableFuture objects using the thenCompose() method, which takes a Function that returns a CompletableFuture object.
1
2
3
CompletableFuture<String> completableFuture = CompletableFuture.supplyAsync(() -> "Hello, world!")
.thenCompose(s -> CompletableFuture.supplyAsync(() -> s + " from CompletableFuture"));
Combining CompletableFuture
You can combine multiple CompletableFuture objects using the thenCombine() method, which takes two CompletableFuture objects and a BiFunction that maps the results of both CompletableFuture objects to a new value.
1
2
3
4
CompletableFuture<Integer> completableFuture1 = CompletableFuture.supplyAsync(() -> 10);
CompletableFuture<Integer> completableFuture2 = CompletableFuture.supplyAsync(() -> 20);
CompletableFuture<Integer> combinedFuture = completableFuture1.thenCombine(completableFuture2, (a, b) -> a + b);
Handling Exceptions
CompletableFuture provides several methods for handling exceptions, including exceptionally() and handle(). The exceptionally() method takes a Function that handles the exception and returns a default value, while the handle() method takes a BiFunction that maps the exception to a new value.
1
2
3
4
5
6
7
8
CompletableFuture<Integer> completableFuture = CompletableFuture.supplyAsync(() -> {
int i = 10 / 0;
return i;
}).exceptionally(ex -> {
System.out.println("Exception occurred: " + ex);
return 0;
});
Timeout
CompletableFuture provides a way to specify a timeout for an asynchronous operation using the completeOnTimeout() and orTimeout() methods.
1
2
3
4
5
6
7
8
9
CompletableFuture<String> completableFuture = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "Hello, world!";
}).completeOnTimeout("Timeout occurred", 3, TimeUnit.SECONDS);
Conclusion
CompletableFuture is a powerful tool for performing asynchronous operations in Java 8. Its API provides support for chaining and composition of operations, error handling, timeouts, and more. If you are working with asynchronous operations in your Java code, you should definitely explore CompletableFuture and see how it can make your code more efficient and scalable.