Java8 - Asynchronous programming

Category : Java | Sub Category : Java8 Features | By Prasad Bonam Last updated: 2023-11-13 07:49:05 Viewed : 239


Asynchronous programming in Java 8 is facilitated by the introduction of the CompletableFuture class in the java.util.concurrent package. CompletableFuture is designed to work with both functional and imperative programming styles, providing a convenient way to work with asynchronous computations. Here is an overview of asynchronous programming in Java 8 using CompletableFuture:

1. Creating Asynchronous Computations:

  • Supplying Async Results: Use CompletableFuture.supplyAsync to asynchronously supply a result.

    java
    CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> "Hello, World");
  • Run Async Tasks: Use CompletableFuture.runAsync for asynchronous tasks without a result.

    java
    CompletableFuture<Void> future = CompletableFuture.runAsync(() -> System.out.println("Async task"));

2. Combining and Chaining Asynchronous Computations:

  • Then Apply: Use thenApply to apply a function to the result of a CompletableFuture.

    java
    CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> "Hello"); CompletableFuture<String> transformedFuture = future.thenApply(s -> s + " World");
  • Then Combine: Use thenCombine to combine the results of two CompletableFuture instances.

    java
    CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> "Hello"); CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> " World"); CompletableFuture<String> combinedFuture = future1.thenCombine(future2, (s1, s2) -> s1 + s2);
  • Then Accept: Use thenAccept to perform an action with the result of a CompletableFuture without returning a result.

    java
    CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> "Hello"); CompletableFuture<Void> actionFuture = future.thenAccept(s -> System.out.println("Result: " + s));
  • Then Compose: Use thenCompose for chaining asynchronous computations where the next stage is dependent on the result of the previous stage.

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

3. Exception Handling:

  • Exception Handling: Use exceptionally or 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());

4. Waiting for Completion:

  • Join or Get: Use join or get to wait for the completion of a CompletableFuture.

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

5. Combining Multiple Futures:

  • All Of: Use CompletableFuture.allOf to wait for the completion of all provided CompletableFuture instances.

    java
    CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> "Hello"); CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> " World"); CompletableFuture<Void> allOfFuture = CompletableFuture.allOf(future1, future2);
  • Any Of: Use CompletableFuture.anyOf to wait for the completion of any of the provided CompletableFuture instances.

    java
    CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> "Hello"); CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> " World"); CompletableFuture<Object> anyOfFuture = CompletableFuture.anyOf(future1, future2);

Example:

Here is a comprehensive example demonstrating various aspects of asynchronous programming using CompletableFuture:

java
import java.util.concurrent.CompletableFuture; public class CompletableFutureExample { public static void main(String[] args) { // Creating asynchronous computations CompletableFuture<String> supplyAsyncFuture = CompletableFuture.supplyAsync(() -> "Hello"); CompletableFuture<Void> runAsyncFuture = CompletableFuture.runAsync(() -> System.out.println("Async task")); // Combining and chaining asynchronous computations CompletableFuture<String> transformedFuture = supplyAsyncFuture.thenApply(s -> s + " World"); CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> "Hello"); CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> " World"); CompletableFuture<String> combinedFuture = future1.thenCombine(future2, (s1, s2) -> s1 + s2); CompletableFuture<String> exceptionHandledFuture = CompletableFuture.supplyAsync(() -> { throw new RuntimeException("Something went wrong"); }).exceptionally(ex -> "Handled Exception: " + ex.getMessage()); // Waiting for completion String result = supplyAsyncFuture.join(); // Combining multiple futures CompletableFuture<Void> allOfFuture = CompletableFuture.allOf(supplyAsyncFuture, runAsyncFuture, transformedFuture, combinedFuture, exceptionHandledFuture); // Handling multiple results CompletableFuture<Object> anyOfFuture = CompletableFuture.anyOf(supplyAsyncFuture, runAsyncFuture, transformedFuture, combinedFuture, exceptionHandledFuture); // Waiting for completion of all futures allOfFuture.join(); // Handling the result of any completed future anyOfFuture.thenAccept(resultObject -> System.out.println("Result of any completed future: " + resultObject)); } }

This example covers the creation, combination, chaining, exception handling, and waiting for completion of CompletableFuture instances, as well as handling multiple results with allOf and anyOf. It provides a comprehensive overview of asynchronous programming in Java 8 using CompletableFuture.

Search
Related Articles

Leave a Comment: