What is CompletableFuture.thenApplyAsync() in Java?

Overview

thenApplyAsync is an instance method that is used to run the passed task in a thread obtained from the default executor/the common pool of ForkJoinPool. The method optionally accepts an Executor. When a custom executor is specified, the passed task is executed in a thread obtained from the passed executor.

The thenApplyAsync method is defined in the CompletableFuture class. The CompletableFuture class is defined in the java.util.concurrent package. To import the CompletableFuture class, check the following import statement.

import java.util.concurrent.CompletableFuture;

Syntax


public <U> CompletableFuture<U> thenApplyAsync(Function<? super T,? extends U> fn)

Parameters

  • Function<? super T,? extends U> fn: This is the task to execute.

Return value

This method returns a new CompletableFuture object.

Example

Let’s see how the thenApplyAsync() method works.

import java.util.concurrent.*;
import java.util.function.Function;
public class Main {
static void sleep(int millis){
try {
Thread.sleep(millis);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
static void executionThread(){
System.out.println("Thread execution - " + Thread.currentThread().getName());
}
public static void main(String[] args) throws ExecutionException, InterruptedException {
CompletableFuture<String> completableFuture = CompletableFuture.supplyAsync(() -> {
sleep(1000);
System.out.println("supplyAsync task");
executionThread();
return "Hello-Educative";
});
Function<String, String> taskToExecute = res -> {
System.out.println("thenApplyAsync task");
sleep(1000);
executionThread();
return res + "-Edpresso";
};
CompletableFuture<String> result = completableFuture.thenApplyAsync(taskToExecute);
sleep(3000);
System.out.println("Result - " + result.get());
}
}

Explanation

  • Lines 1–2: We import the relevant packages and classes.

  • Lines 6–12: We define a function called sleep(), which makes the current thread sleep for the given amount of time (in milliseconds).

  • Lines 14–16: We define a function called executionThread(), which prints the current thread of execution.

  • Lines 19–24: We create a completable future called completableFuture using the supplyAsync() method. We pass a supplier to it that sleeps for one second and then invokes the executionThread(). Finally, this method returns a string value.

  • Lines 26–31: We define a task taskToExecute to complete once the completableFuture is completed. The task is a function that sleeps for one second and then invokes the executionThread(). Finally, this method returns the future result appended with a string.

  • Line 33: We call the thenApplyAsync method on completableFuture. We pass taskToExecute as an argument to the method. This returns a new CompletableFuture object called result.

  • Line 35: The main thread is made to sleep for two seconds.

  • Line 36: We print the value of result to the console.