CompletableFuture - Java Async Programming
Methods used in the below examples of serial execution of the completablefutures:
- thenCompose () : Supplies the result of the completion stage as input and returns a new CompletionStage that holds the result of the computation passed inside the function.
- completedFuture(): Returns a completed CompletableFuture wrapped with the passed value to the method.
Executing Completable Futures in serial : Execute all CompletableFuture in Serial
package completables; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionStage; import java.util.concurrent.ExecutionException; public class CompletableFuturesSerialExecution_All { public static void main(String[] args) throws InterruptedException, ExecutionException { CompletableFuturesSerialExecution_All completableFuturesSerialExecution = new CompletableFuturesSerialExecution_All(); completableFuturesSerialExecution.executeCompletableFuturesSerially(); } private void executeCompletableFuturesSerially() throws InterruptedException, ExecutionException { TaskImpl customRuleNumber = new TaskImpl(); for (int i = 0; i < 5; i++) { CompletableFuture<String> completableFuture = CompletableFuture.completedFuture(null); completableFuture = executeRule(completableFuture, i, customRuleNumber); } } private CompletableFuture<String> executeRule(CompletableFuture<String> completableFuture, int i, TaskImpl customRuleNumber) throws InterruptedException, ExecutionException { return completableFuture.thenCompose(__ -> customRuleNumber.executeRule(i)); } abstract class Task { abstract CompletionStage<String> executeRule(int n); } class TaskImpl extends Task { CompletableFuture<String> executeRule(int n) { System.out.println("Executing Task number = " + n); return CompletableFuture.completedFuture("" + n); }; } } Execution Output: Executing Task number = 0 Executing Task number = 1 Executing Task number = 2 Executing Task number = 3 Executing Task number = 4Here in the above example, we are executing multiple tasks in the completable futures in
serial order.
Executing Completable Futures in serial : return after one of the futures return the response
package completables; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionStage; import java.util.concurrent.ExecutionException; public class CompletableFutureSerial_breakAfterResult { public static void main(String[] args) throws InterruptedException, ExecutionException { CompletableFutureSerial_breakAfterResult completableFuturesSerialExecution = new CompletableFutureSerial_breakAfterResult(); completableFuturesSerialExecution.executeCompletableFuturesSerially(); } private void executeCompletableFuturesSerially() throws InterruptedException, ExecutionException { TaskImpl customRuleNumber = new TaskImpl(); for (int i = 0; i < 5; i++) { CompletableFuture<String> completableFuture = CompletableFuture.completedFuture(null); completableFuture = executeRule(completableFuture, i, customRuleNumber); if (completableFuture.get() != null) { System.out.println("Task executed and returned non-null result : Task Number = " + completableFuture.get()); break; } } } private CompletableFuture<String> executeRule(CompletableFuture<String> completableFuture, int i, TaskImpl customRuleNumber) throws InterruptedException, ExecutionException { return completableFuture.thenCompose(__ -> customRuleNumber.executeRule(i)); } abstract class Task { abstract CompletionStage<String> executeRule(int n); } class TaskImpl extends Task { CompletableFuture<String> executeRule(int n) { if (n == 1) { System.out.println("Executing Task number = " + n); return CompletableFuture.completedFuture("" + n); } System.out.println("returns null"); return CompletableFuture.completedFuture(null); }; } } Output: returns null Executing Task number = 1 Task executed and returned non-null result : Task Number = 1Here in the above example Tas- 0 returns null , then execution continues and when task-1 return the
non-null object then we stop the execution as we have got our result.
We can put a different condition according to our use case and break whenever we want to get out of
the serial execution.