Java8 - Introduction to Completable Future

Category : Java | Sub Category : Java8 Features | By Prasad Bonam Last updated: 2023-11-13 07:41:21 Viewed : 144


CompletableFuture is a class introduced in Java 8 as part of the java.util.concurrent package. It represents a promise that can be completed with a value or an exception in an asynchronous computation. It provides a way to perform computations asynchronously and enables the composition of multiple asynchronous operations.

Key features and concepts related to CompletableFuture include:

1. Asynchronous Computation:

  • CompletableFuture is designed to handle asynchronous computations, allowing you to perform tasks in the background without blocking the main thread.

2. Composition:

  • CompletableFuture supports the composition of multiple asynchronous operations. You can chain multiple CompletableFuture instances together to create a pipeline of operations.

3. Callback Functions:

  • Callback functions can be attached to a CompletableFuture to be executed upon completion. These callbacks are invoked when the CompletableFuture completes either normally or exceptionally.

4. Combining Results:

  • CompletableFuture provides methods for combining the results of multiple CompletableFuture instances. For example, you can use thenCombine to combine the results of two CompletableFuture instances when they both complete.

5. Exception Handling:

  • Exceptional completion is supported, allowing you to handle exceptions that may occur during the asynchronous computation.

6. Timeouts and Cancelling:

  • CompletableFuture supports specifying timeouts for operations and allows canceling the computation if it takes too long.

Example:

Here is a simple example that demonstrates the basics of CompletableFuture:

java
import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; public class CompletableFutureExample { public static void main(String[] args) { // Create a CompletableFuture CompletableFuture<String> completableFuture = CompletableFuture.supplyAsync(() -> "Hello, ") .thenApplyAsync(result -> result + "world") .thenApply(String::toUpperCase); // Attach a callback for when the CompletableFuture completes successfully completableFuture.thenAcceptAsync(result -> System.out.println("Result: " + result)); // Attach a callback for handling exceptions completableFuture.exceptionally(ex -> { System.err.println("Exception: " + ex.getMessage()); return null; }); // Wait for the CompletableFuture to complete (blocking) try { completableFuture.get(); } catch (InterruptedException | ExecutionException e) { e.printStackTrace(); } } }

In this example:

  • supplyAsync starts an asynchronous computation that produces the string "Hello, ".
  • thenApplyAsync applies a function that concatenates "world" to the result.
  • thenApply converts the result to uppercase.
  • thenAcceptAsync prints the final result.
  • exceptionally handles exceptions that may occur during the computation.

CompletableFuture provides a rich set of methods for handling various scenarios in asynchronous programming. It is widely used in scenarios where you need to perform operations concurrently, such as parallelizing tasks, handling callbacks, and composing complex asynchronous workflows.

CompletableFuture is a class in Java introduced in Java 8 as part of the java.util.concurrent package. It is an implementation of the Future interface and provides a powerful and flexible way to perform asynchronous programming and handle asynchronous computations. CompletableFuture is designed to work with both functional and imperative programming styles, making it versatile for various concurrency scenarios.

Here are some key aspects of CompletableFuture:

Asynchronous Execution:

  • CompletableFuture for Async Execution: CompletableFuture allows you to perform tasks asynchronously. You can use methods like supplyAsync, runAsync, and various combinators to create and compose asynchronous computations.

    java
    CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> "Hello");

Composing Futures:

  • Combining Multiple Futures: CompletableFuture provides methods like thenApply, thenAccept, and thenCombine for combining multiple CompletableFuture instances. This allows you to create a pipeline of asynchronous operations.

    java
    CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> "Hello"); CompletableFuture<String> transformedFuture = future.thenApply(s -> s + " World");

Exception Handling:

  • Exception Handling: CompletableFuture supports exceptional completion. You can use methods like exceptionally and handle to handle exceptions that occur during the computation.

    java
    CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> { // Some computation that may throw an exception throw new RuntimeException("Something went wrong"); }); CompletableFuture<String> resultFuture = future.exceptionally(ex -> "Handled Exception: " + ex.getMessage());

Combining Results:

  • Combining Results of Multiple Futures: CompletableFuture provides methods like thenCombine, thenCompose, and allOf for combining the results of multiple asynchronous computations.

    java
    CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> "Hello"); CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> " World"); CompletableFuture<String> combinedFuture = future1.thenCombine(future2, (s1, s2) -> s1 + s2);

Waiting for Completion:

  • Waiting for Completion: You can wait for the completion of a CompletableFuture using methods like get or join. These methods block until the result of the computation is available.

    java
    CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> "Hello"); String result = future.join(); // or future.get()

Handling Multiple Results:

  • Handling Multiple Results: CompletableFuture provides the allOf and anyOf methods to deal with multiple CompletableFuture instances simultaneously.

    java
    CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> "Hello"); CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> " World"); CompletableFuture<Void> allOfFuture = CompletableFuture.allOf(future1, future2);

Example:

Here is a simple example demonstrating some of the features of CompletableFuture:

java
import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; public class CompletableFutureExample { public static void main(String[] args) throws ExecutionException, InterruptedException { CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> "Hello"); // Applying a transformation CompletableFuture<String> transformedFuture = future.thenApply(s -> s + " World"); // Handling exceptions CompletableFuture<String> exceptionHandledFuture = future.exceptionally(ex -> "Handled Exception: " + ex.getMessage()); // Combining results of multiple futures CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> "Hello"); CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> " World"); CompletableFuture<String> combinedFuture = future1.thenCombine(future2, (s1, s2) -> s1 + s2); // Waiting for completion String result = future.join(); // or future.get() System.out.println("Original Result: " + result); System.out.println("Transformed Result: " + transformedFuture.get()); System.out.println("Exception Handled Result: " + exceptionHandledFuture.get()); System.out.println("Combined Result: " + combinedFuture.get()); } }

This example demonstrates creating and working with CompletableFuture instances, applying transformations, handling exceptions, combining results, and waiting for completion. CompletableFuture is a powerful tool for building concurrent and asynchronous applications in Java.

Search
Related Articles

Leave a Comment: