You are currently viewing Asynchronous Programming with CompletableFuture in Java 8

Asynchronous Programming with CompletableFuture in Java 8

  • Post author:
  • Post category:Java
  • Post comments:0 Comments
  • Post last modified:February 22, 2024

In Java programming, asynchronous programming is crucial for building responsive and scalable applications. Java 8 introduced the CompletableFuture class, which provides a powerful way to work with asynchronous tasks. In this article, we’ll explore CompletableFuture and its various features with examples.

Introduction to CompletableFuture

CompletableFuture is a class added in Java 8 that represents a future result of an asynchronous computation. It allows you to perform operations asynchronously and handle the result when it becomes available. CompletableFuture offers a fluent and flexible API for composing asynchronous tasks, chaining them together, and handling exceptions.

Creating CompletableFuture Instances

You can create CompletableFuture instances in several ways:

  1. Using static factory methods:
   CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> "Hello");
  1. Using a custom Executor:
   Executor executor = Executors.newFixedThreadPool(5);
   CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> 42, executor);

Chaining CompletableFuture Operations

CompletableFuture allows you to chain asynchronous operations together using various methods like thenApply, thenCompose, thenCombine, etc. Here’s an example of chaining:

CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> 10)
    .thenApply(result -> result * 2)
    .thenApply(result -> result + 5);

Combining Multiple CompletableFutures

You can combine the results of multiple CompletableFuture instances using methods like thenCombine, thenAcceptBoth, or allOf. For example:

CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(() -> 10);
CompletableFuture<Integer> future2 = CompletableFuture.supplyAsync(() -> 20);

CompletableFuture<Integer> combinedFuture = future1.thenCombine(future2, (result1, result2) -> result1 + result2);

Handling Errors and Exceptions

CompletableFuture provides methods like exceptionally and handle for handling errors and exceptions gracefully:

CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
    if (someCondition) {
        throw new RuntimeException("Error occurred");
    return 42;
}).exceptionally(ex -> {
    System.out.println("Exception occurred: " + ex.getMessage());
    return 0;

Asynchronous Tasks with CompletableFuture

CompletableFuture supports various asynchronous tasks such as:

  • Async computations: Performing CPU-intensive or blocking tasks asynchronously.
  • IO operations: Reading from files, making HTTP requests, or querying databases asynchronously.
  • Timeouts: Setting timeouts for asynchronous tasks to prevent blocking indefinitely.
  • Error recovery: Handling exceptions and errors gracefully.


CompletableFuture in Java 8 is a powerful tool for writing asynchronous and non-blocking code. It offers a fluent and flexible API for composing, chaining, and combining asynchronous tasks. By leveraging CompletableFuture, you can build responsive and scalable applications that can handle concurrent tasks efficiently.

In this article, we covered the basics of CompletableFuture and demonstrated its usage with examples. We explored how to create CompletableFuture instances, chain asynchronous operations, combine multiple CompletableFutures, handle errors, and perform various asynchronous tasks. With its rich set of features, CompletableFuture simplifies asynchronous programming in Java and enables developers to write more efficient and responsive code.

Leave a Reply