CompletableFuture Summary

Kablumndl
8 min readJul 1, 2021
CompletionStage Interface
CompletionStage interface represents a communication task
(either synchronous or asynchronous). All method declared
in this interface return an instance of CompletionStage itself,
so multiple CompletionStage can be chained and create a pipeline together. individual task are combined in different ways to complete a group of tasks.
A stage of a possibly asynchronous computation, that performs an action or computes a value when another CompletionStage completes. Once a stage complete its computation then it turns trigger
other dependent stages.
The computation performed by a stage may be expressed as a Function, Consumer,or Runnable (using methods with names including apply, accept, or run, respectively) depending on whether it requires arguments and/or produces results.

For example,
stage.thenApply(x -> square(x))
.thenAccept(x -> System.out.print(x))
.thenRun(() -> System.out.println())
An additional form (compose) applies functions of stages themselves, rather than their results.
One stage’s execution may be triggered by completion of a single stage, or both of two stages, or either of two stages.
Dependencies on a single stage are arranged using methods with prefix then. Those triggered by completion of both of two stages may combine their results or effects,using correspondingly named methods. Those triggered by either of two stages make no guarantees about which of the results or effects are used for the dependent stage’s computation.
Dependencies among stages control the triggering of computations,
but do not otherwise guarantee any particular ordering.
Additionally, execution of a new stage’s computations may be arranged in any of three ways: default execution, default asynchronous execution (using methods with suffix async that employ the stage’s default asynchronous execution facility),
or custom (via a supplied Executor).
The execution properties of default and async modes are specified by CompletionStage implementations, not this interface.
Methods with explicit Executor arguments may have arbitrary execution properties, and might not even support concurrent execution, but are arranged for processing in a way that accommodates asynchrony.
Two method forms support processing whether the triggering stage completed normally or exceptionally:-
Method whenComplete allows injection of an action regardless of outcome, otherwise preserving the outcome
in its completion. Method handle additionally allows the stage to compute a replacement result that may enable further processing by other dependent stages.
In all other cases, if a stage’s computation terminates abruptly with an (unchecked) exception or error,then all dependent stages requiring its completion complete exceptionally as well,
with a CompletionException holding the exception as its cause.
If a stage is dependent on both of two stages, and both complete exceptionally,then the CompletionException may correspond to either one of these exceptions.
If a stage is dependent on either of two others, and only one of them completes exceptionally,no guarantees are made about whether the dependent stage completes normally or exceptionally.
In the case of method whenComplete, when the supplied action itself encounters an exception,then the stage exceptionally completes with this exception if not already completed exceptionally.
All methods adhere to the above triggering, execution, and exceptional completion specifications (which are not repeated in individual method specifications). Additionally, while arguments used to pass a completion result (that is, for parameters of type T)
for methods accepting them may be null, passing a null value for any other parameter will result in a NullPointerException being thrown.
This interface does not define methods for initially creating, forcibly completing normally or exceptionally, probing completion status or results, or awaiting completion of a stage.
Implementations of CompletionStage may provide means of achieving such effects, as appropriate. Method toCompletableFuture() enables interoperability among different implementations of this
interface by providing a common conversion type.
CompletableFuture is a way to do asynchronous & non-blocking code where each task run in a separate thread and notify about the progress to the main thread either it complete normally or exceptionally.Using this wat the main thread will not block/wait and it can do other task parallely.
Doing this kind of processing will improve performance of the code.

SupplyAsync

import java.util.concurrent.CompletableFuture;import java.util.concurrent.ExecutionException;public class SupplyAsyncWithOneParameter {public static void main(String[] args) {try {new SupplyAsyncWithOneParameter().supplyAsyncDemo(“Mandal”);new SupplyAsyncWithOneParameter().supplyAsyncDemo(“Amit”);new SupplyAsyncWithOneParameter().supplyAsyncDemoWithThenApplyAsync(“Nikhil”);boolean supplyAsyncDemoWithThenApplyAsyncComplete = new SupplyAsyncWithOneParameter().supplyAsyncDemoWithThenApplyAsyncComplete(“Piyush”);System.out.println(“supplyAsyncDemoWithThenApplyAsyncComplete:” + supplyAsyncDemoWithThenApplyAsyncComplete);} catch (InterruptedException | ExecutionException e) {e.printStackTrace();}}public void supplyAsyncDemo(String name) throws InterruptedException, ExecutionException {System.out.println(“@@inside supplyAsyncDemo..”);CompletableFuture<String> cf = CompletableFuture.supplyAsync(() -> {System.out.println(“Thread Name 1:” + Thread.currentThread().getName());return “Hi “ + name;}).thenApply(n -> {System.out.println(“Thread Name 2:” + Thread.currentThread().getName());return n + “ How are you.”;}).thenApply(s -> {System.out.println(“Thread Name 3:” + Thread.currentThread().getName());return s + “ Welcome to the completable futre”;});System.out.println(cf.get());}public void supplyAsyncDemoWithThenApply(String name) throws InterruptedException, ExecutionException {System.out.println(“@@inside supplyAsyncDemoWithThenApply..”);CompletableFuture.supplyAsync(() -> {System.out.println(“Thread Name 1:” + Thread.currentThread().getName());return “Hi “ + name;}).thenApply(n -> {System.out.println(“Thread Name 2:” + Thread.currentThread().getName());return n + “ How are you.”;}).thenApply(s -> {System.out.println(“Thread Name 3:” + Thread.currentThread().getName());return s + “ Welcome to the completable futre”;}).thenAccept(System.out::println);}public void supplyAsyncDemoWithThenApplyAsync(String name) throws InterruptedException, ExecutionException {System.out.println(“@@inside supplyAsyncDemoWithThenApply..”);CompletableFuture.supplyAsync(() -> {System.out.println(“Thread Name 1:” + Thread.currentThread().getName());return “Hi “ + name;}).thenApplyAsync(n -> {System.out.println(“Thread Name 2:” + Thread.currentThread().getName());return n + “ How are you.”;}).thenApplyAsync(s -> {System.out.println(“Thread Name 3:” + Thread.currentThread().getName());return s + “ Welcome to the completable futre”;}).thenAccept(System.out::println);}public boolean supplyAsyncDemoWithThenApplyAsyncComplete(String name) throws InterruptedException, ExecutionException {System.out.println(“@@inside supplyAsyncDemoWithThenApplyAsyncComplete..”);CompletableFuture<String> cf = CompletableFuture.supplyAsync(() -> {System.out.println(“Thread Name 1:” + Thread.currentThread().getName());try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}return “Hi “ + name;}).thenApplyAsync(n -> {System.out.println(“Thread Name 2:” + Thread.currentThread().getName());try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}return n + “ How are you.”;}).thenApplyAsync(s -> {System.out.println(“Thread Name 3:” + Thread.currentThread().getName());return s + “ Welcome to the completable futre”;});return cf.complete(“Default Complete”);}}

SupplyAsyncWithExecutor

import java.util.concurrent.CompletableFuture;import java.util.concurrent.ExecutionException;import java.util.concurrent.Executors;public class SupplyAsyncWithExecutor {public static void main(String[] args) {try {new SupplyAsyncWithExecutor().supplyAsyncDemo(“Mandal”);} catch (InterruptedException | ExecutionException e) {e.printStackTrace();}}public void supplyAsyncDemo(String name) throws InterruptedException, ExecutionException {System.out.println(“@@inside supplyAsyncDemo..”);CompletableFuture<String> cf = CompletableFuture.supplyAsync(() -> {System.out.println(“Thread Name 1:” + Thread.currentThread().getName());return “Hi “ + name;}, Executors.newCachedThreadPool()).thenApply(n -> {System.out.println(“Thread Name 2:” + Thread.currentThread().getName());return n + “ How are you.”;}).thenApply(s -> {System.out.println(“Thread Name 3:” + Thread.currentThread().getName());return s + “ Welcome to the completable futre”;});System.out.println(cf.get());}}

WhenCompleteExample

package com.learnJava.completable.future;import java.util.concurrent.CompletableFuture;public class WhenCompleteExample {public static void main(String[] args) {new WhenCompleteExample().show(20);}public void show(int i) {System.out.println(“@@inside show…”);CompletableFuture.supplyAsync(() -> {return 100/i;}).whenComplete((a, ex) -> {System.out.println(“whenComplete”);if(ex != null) {System.out.println(“exception occurs”);System.err.println(ex);}}).handle((result, exep) -> {System.out.println(“Handle”);if (result != null) {return result;} else {return “Error handling: “ + exep.getMessage();}}).exceptionally(th -> {System.out.println(“Exception with thrown” + th);return 1;}).thenAccept(System.out::println);}}

CompletableFutureThenRun

import java.util.concurrent.CompletableFuture;import java.util.concurrent.ExecutionException;public class CompletableFutureThenRun {public static void main(String[] args) throws InterruptedException, ExecutionException {CompletableFuture.supplyAsync(() -> {System.out.println(“Thread 1 Name:” + Thread.currentThread());return 20;}).thenRunAsync(() -> {System.out.println(“I am the second one ,,name is :” + Thread.currentThread().getName());}).thenRun(() -> {System.out.println(“thenRun executed”);System.out.println(“Thread 2 Name:” + Thread.currentThread());}).get();}}

CompletableFutureThenCompose

import java.util.concurrent.CompletableFuture;import java.util.concurrent.ExecutionException;public class CompletableFutureThenCompose {public static void main(String[] args) throws InterruptedException, ExecutionException {CompletableFuture<Integer> thenCompose = CompletableFuture.supplyAsync(() -> 33).thenCompose(t -> CompletableFuture.supplyAsync(() -> 2 + t));System.out.println(thenCompose.get());}}

CompletableFutureThenCombine

import java.util.concurrent.CompletableFuture;import java.util.concurrent.ExecutionException;public class CompletableFutureThenCombine {public static void main(String[] args) throws InterruptedException, ExecutionException {Integer s = CompletableFuture.supplyAsync(() -> 2).thenCombine(CompletableFuture.supplyAsync( () -> 5), (a, b) -> {return a + b;}).get();System.out.println(s);}}

CompletableFutureThenapplyWithexecutor

import java.util.concurrent.CompletableFuture;import java.util.concurrent.ExecutionException;import java.util.concurrent.Executors;public class CompletableFutureThenapplyWithexecutor {public static void main(String[] args) throws InterruptedException, ExecutionException {CompletableFuture.supplyAsync(() -> {return 20;}, Executors.newCachedThreadPool()).thenApply(s-> {return s*10;}).thenAccept(System.out::println);}}

CompletableFutureRunAsync

import java.util.concurrent.CompletableFuture;import java.util.concurrent.ExecutionException;public class CompletableFutureRunAsync {public static void main(String[] args) throws InterruptedException, ExecutionException {CompletableFuture.supplyAsync(() -> {return 20;}).thenRun(() -> {System.out.println(“thenRun executed”);}).get();new CompletableFutureRunAsync().runAsyncDemo();}public void runAsyncDemo() {System.out.println(“runAsyncDemo…”);CompletableFuture.runAsync(() -> {System.out.println(“Task 1 Is Going On…”);}).thenAccept(System.out::println);}

CompletableFutureOnlineShopping

import java.util.concurrent.CompletableFuture;public class CompletableFutureOnlineShopping {public static Integer placeOrder() {System.out.println(“placeOrder:” + Thread.currentThread());return 1;}public static Integer approveOrder(Integer placeOder) {System.out.println(“approveOrder:” + Thread.currentThread());return 1 + placeOder;}public static Integer orderPrepare(int approveOrder) {System.out.println(“orderPrepare:” + Thread.currentThread());return 1 + approveOrder;}public static Integer OrderDispatch(int orderPrepare) {System.out.println(“OrderDispatch:” + Thread.currentThread());return 1 + orderPrepare;}public static Integer OrderDelivered(int OrderDispatch) {System.out.println(“OrderDelivered:” + Thread.currentThread());return 1 + OrderDispatch;}public static CompletableFuture<Integer> create() {return CompletableFuture.supplyAsync(() -> placeOrder());}public static CompletableFuture<Integer> received(int rec) {return CompletableFuture.supplyAsync(() -> approveOrder(rec));}public static void main(String[] args) {CompletableFuture<Integer> create = create();create//.thenAccept(System.out::println).thenApply(a -> received(a)).thenAccept(System.out::println);//Returns a new CompletionStage that, when this stage completesnormally,//is executed using this stage’s default asynchronousexecution facility, with this stage’s result as the argument tothe supplied function.CompletableFuture.supplyAsync(() -> placeOrder()).thenApplyAsync(a -> approveOrder(a)).thenApply(b -> orderPrepare(b)).thenApply(c -> OrderDispatch(c)).thenApply(d -> OrderDelivered(d)).thenAccept(System.out::println);System.out.println(“main:” + Thread.currentThread());}}

CompletableFutureExceptionally

import java.util.concurrent.CompletableFuture;public class CompletableFutureExceptionally {public static void main(String[] args) {String name = null;CompletableFuture<String> cf = CompletableFuture.supplyAsync(() -> {if(name == null) throw new IllegalArgumentException(“Invalid String Value Passed:” + name);return name;}).exceptionally((e) -> {System.out.println(“Exception Thrown With Message:” + e.getMessage());return “”;});}}

CompletableFutureCombine

import java.util.concurrent.CompletableFuture;public class CompletableFutureCombine {public static CompletableFuture<Integer> create(int n) {return CompletableFuture.supplyAsync(() -> n);}public static void main(String[] args) {create(2).thenCombine(create(3), (a, b) -> a+b).thenAccept(System.out::println);}}

CompletableFutreThenCombine

import java.util.concurrent.CompletableFuture;import java.util.concurrent.ExecutionException;public class CompletableFutreThenCombine {public static void main(String[] args) {try {new CompletableFutreThenCombine().completableFutThenCombine();} catch (InterruptedException | ExecutionException e) {// TODO Auto-generated catch blocke.printStackTrace();}}public void completableFutThenCombine() throws InterruptedException, ExecutionException {CompletableFuture cf1 = CompletableFuture.supplyAsync(() -> {System.out.println(“Thread Name 1:” + Thread.currentThread().getName());return “Token ID:001”;});CompletableFuture cf2 = CompletableFuture.supplyAsync(() -> {System.out.println(“Thread Name 2:” + Thread.currentThread().getName());return “Vaccine Name:Covaxin”;});CompletableFuture thenCombine = cf1.thenCombine(cf2, (token, vaccName) -> {System.out.println(“Thread Name 3:” + Thread.currentThread().getName());return “Your Details: Token Id is:” + token + “ and” + vaccName;});CompletableFuture thenCombineAsync = cf1.thenCombineAsync(cf2, (token, vaccName) -> {System.out.println(“Thread Name 3:” + Thread.currentThread().getName());return “Your Details: Token Id is:” + token + “ and” + vaccName;});System.out.println(thenCombine.get());System.out.println(thenCombineAsync.get());}}

CompletableFutreAllOf

import java.util.Arrays;import java.util.List;import java.util.concurrent.CompletableFuture;import java.util.concurrent.ExecutionException;import java.util.concurrent.TimeUnit;import java.util.stream.Collectors;public class CompletableFutreAllOf {public static CompletableFuture<String> showMobile(String brand) {return CompletableFuture.supplyAsync(() -> {try {TimeUnit.SECONDS.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}return brand.toUpperCase();});}public static void main(String[] args) throws InterruptedException, ExecutionException {List<CompletableFuture<String>> listofcf = Arrays.asList(“nokia”,”samsung”,”apple”,”lg”,”onida”).stream().map(b -> showMobile(b)).collect(Collectors.toList());CompletableFuture<Void> allFutures = CompletableFuture.allOf(listofcf.toArray(new CompletableFuture[listofcf.size()]));CompletableFuture<List<String>> allPageContentsFuture = allFutures.thenApply(v -> {return listofcf.stream().map(s -> s.join()).collect(Collectors.toList());});System.out.println(allPageContentsFuture);}}

CompletableFutreAcceptEither

import java.util.concurrent.CompletableFuture;import java.util.concurrent.ExecutionException;import java.util.concurrent.TimeUnit;public class CompletableFutreAcceptEither {public static CompletableFuture<Integer> m1() {return CompletableFuture.supplyAsync(() -> {try {TimeUnit.SECONDS.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}return 20;});}public static CompletableFuture<Integer> m2() {return CompletableFuture.supplyAsync(() -> {try {TimeUnit.SECONDS.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}return 30;});}public static void main(String[] args) throws InterruptedException, ExecutionException {m1().acceptEither(m2(), t-> {System.out.println(“t = “ + t);}).get();}}

************************************************************

--

--

Kablumndl

Java Developer, Software Engineer, Spring, Spark, MicroService, PostgresSQL