Home » CompletableFuture supplyasync example

CompletableFuture supplyasync example

  • by
CompletableFuture runAsync and supplyAsync

1. Overview

In this article, we will discuss the supplyAsync methods of the CompletableFuture interface with example. This CompletableFuture interface was added to the java.util.concurrent package in the Java 8 release.

2. CompletableFuture supplyAsync

You can use the CompletableFuture interface for asynchronous programming. In other words, this interface runs the non-blocking code as a task in a non-blocking thread. After execution, it notifies the caller thread about the task progress, completion, or any failure.

This CompletableFuture has the following methods to execute the code:

1. supplyAsync

This method takes a Supplier<U> as an argument and returns the CompletableFuture<U> instance back to the caller thread. A supplier is nothing but a function that contains the code to be executed asynchronously. This function returns a value that you can retrieve later by using the CompletableFuture<U> instance.

2. RunAsync

This method accepts a Runnable as an input parameter and returns CompletableFuture<Void>. If you notice, the type of the CompletableFuture is void, meaning this method won’t return any result back to the caller.

We have seen the differences between the supplyAsync and runAsync. Now let’s understand each of these functions with examples.

2.1. CompletableFuture supplyAsync with common pool

The supplyAsync method uses the common pool if no executor is specified:

public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier)

The above supplyAsync uses the threads from the common pool (ForkJoinPool#commonPool) to execute the non-blocking code.

The following code uses the supplyAsync method which internally gets thread from the common pool. Also, the supplyAsync returns CompletableFuture<String> instance as the return type of supplier function is String.

public static void main(String[] args) throws ExecutionException, InterruptedException {
        System.out.println(ForkJoinPool.getCommonPoolParallelism());
        CompletableFuture<String> cf = CompletableFuture.supplyAsync(() -> {
            System.out.println("SupplyAsync : " +
                    Thread.currentThread().getName());
            return "Success";
        });
}

If you execute the above code, you can see in the console that the supplier code is executed by the worker thread of ForkJoinPool#commonPool.

SupplyAsync : ForkJoinPool.commonPool-worker-3

Note that the supplier method returns a string as output. You can retrieve this result string by using the callbacks available with CompletableFuture.

For example, the whenComplete method executes after the non-blocking supplier code completes its execution or throws any exception. You can retrieve the return value of the supplier method inside this function. Therefore, the below method prints the return value "Success".

cf.whenComplete((result, throwable) ->
                {
                    if (throwable == null) {
                        System.out.println("whenComplete : "
                                + result
                                + " in thread. " + Thread.currentThread().getName());
                    }
                });
/* prints whenComplete : Success in thread. ForkJoinPool.commonPool-worker-3 */

2.2. CompletableFuture supplyAsync with executor

The following supplyAsync takes both the supplier function and executor. It uses the threads specified in the executor to run the supplier (non-blocking) code. This method returns CompletableFuture<U> instance, meaning the supplier function returns value of type U.

public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier, Executor executor)

In the below code, we are creating a fixed thread pool using the Executor. The executor is passed as an argument to the supplyAsync method. Also, the supplyAsync returns CompletableFuture<String> instance as the return type of supplier function is String.

ExecutorService e = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors(),
                r -> new Thread(r, "supplyAsycPool"));
CompletableFuture<String> cf = CompletableFuture.supplyAsync(() -> {
      System.out.println("supplyAsync executed in the thread of passed executor: " +
                Thread.currentThread().getName());
      return "Success";
}, e);

If you run the above code, then you can notice that the non-blocking supplier code is executed by the thread created in the executor.

supplyAsync executed in the thread of passed executor: supplyAsycPool

The supplyAsync method returns a string as output. You can retrieve this result string by using the callbacks available with CompletableFuture.

For example, the whenComplete method executes after the non-blocking supplier code completes its execution or throws any exception.

You can retrieve the return value of the supplier method inside this function. Therefore, the below method prints the return value "Success".

cf.whenComplete((result, throwable) ->
                {
                    if (throwable == null) {
                        System.out.println("whenComplete : "
                                + result
                                + " in thread. " + Thread.currentThread().getName());
                    }
                });
/* prints 
whenComplete : Success in thread. supplyAsycPool */

If you execute the above code, then you can notice that the runAsync supplier code ran using the common pool thread.

runAsync executed in the thread: ForkJoinPool.commonPool-worker-3

3. Conclusion

To sum up, we have learned the purpose of supplyAsync method available in the CompletableFuture along with an example. If you don’t want any output or result from the non-blocking code, then use runAsync. Otherwise, use supplyAsync method to execute your non-blocking code.

To learn more about Java, refer to our articles.

Leave a Reply

Your email address will not be published.