SlideShare a Scribd company logo
Leveraging CompletableFutures to handle
your query results asynchronously
David Gómez G.


Developer Advocate
Concurrency


vs


Parallelism
Same type of tasks


Workload split between similar workers


Have the work finished before
Parallelism Concurrency
Different type of tasks


Usually do some works while waiting for
other tasks to be completed.


Have the work finished before
@DGOMEZG
Java and Concurrency
Lots of tools since Java 1
Java has (basic) building blocks for Concurrency and parallelism
since Java 1.


Even when most desktop computers were single-core
@DGOMEZG
Threads
Very Expensive
Thread t = new Thread(task);

t.start();

t.join();

Easily forgotten
Blocking call
ThreadPools
@DGOMEZG
ThreadPools
@DGOMEZG
ThreadPools
@DGOMEZG
ThreadPools
@DGOMEZG
ThreadPools
@DGOMEZG
Since Java 5
Concurrency & parallelism support improved in Java 5


Lots of New Concurrency constructors


New concurrent-friendly Data Structures


Revisited and improved in Java 7, 8, 9 …


More coming up as part of loom project
@DGOMEZG
Running tasks
asynchronously
ExecutorService
And now we can submit:


- tasks that do not return anything. Runnable


- tasks that return a result. Callable<R>


Executor Service returns a Future<R>
@DGOMEZG
ExecutorService & Future<T>
ExecutorService executorService = Executors.newCachedThreadPool();

Future<String> taskResult = 

executorService.submit(longRunningTaskWithResult);
String s = taskResult.get();
Blocking call
ExecutorService & Future<T>
ExecutorService executorService = Executors.newCachedThreadPool();

Future<String> taskResult = 

executorService.submit(longRunningTaskWithResult);
while (!taskResult.isDone()) {

doSomethingElse();

}

String s = taskResult.get();

False while task is not cancelled
nor
fi
nished
Improving performance by doing
other tasks.
Running Multiple T
asks
List<Future<String
>
>
taskResults = new ArrayList
<
>
();

for (Callable<String> task : tasks) {

taskResults.add(executorService.submit(task));

}

for (Future<String> result : taskResults) {

processResult(result.get());

}

Bene
fi
t only between submitting
all tasks and getting the results
Running Heterogeneous T
asks
List<Future<String
>
>
taskResults = new ArrayList
<
>
();

for (Callable<String> task : tasks) {

taskResults.add(executorService.submit(task));

}

for (Future<String> result : taskResults) {

processResult(result.get());

}
 What if task1 is too slow
while task2 is fast?
What if we need the result of
task1 to submit task2?
(CompletionService returns
tasks in the order they are
fi
nished)
CompletableFuture
CompletableFuture<T>
Introduced in Java8


Has specific methods to submit tasks to an ExecutorService


Implements a fluent API (CompletionStage) that allows chaining and
combining dependant tasks.


Allow to use different sized ExecutorServices for different tasks.
@DGOMEZG
Async with CompletableFuture
CompletableFuture.runAsync(getLongRunningTaskWithNoResult());
Async with CompletableFuture
CompletableFuture<Void> voidCF = 

CompletableFuture.runAsync(getLongRunningTaskWithNoResult());

doSomethingElse();
Async with CompletableFuture
CompletableFuture<Void> voidCF = 

CompletableFuture.runAsync(getLongRunningTaskWithNoResult());

doSomethingElse();

CompletableFuture<Void> voidCF = 

CompletableFuture.runAsync(getLongRunningTaskWithNoResult());

doSomethingElse();

voidCF.get();
/
/
Wait until background task is finished
Async with CompletableFuture
CompletableFuture<Void> voidCF = 

CompletableFuture.runAsync(getLongRunningTaskWithNoResult());

doSomethingElse();

voidCF.get();
/
/
Wait until background task is finished
private static final Executor ASYNC_POOL = USE_COMMON_POOL ?

ForkJoinPool.commonPool() : new ThreadPerTaskExecutor();
Async with CompletableFuture
private static final Executor ASYNC_POOL = USE_COMMON_POOL ?

ForkJoinPool.commonPool() : new ThreadPerTaskExecutor();
Shared with the JVM (may affect parallel
streams)


Sized for CPU intensive tasks (if our task is
IO bound, we may affect app performance)


Daemon Threads (if our main thread
finishes, tasks may not be executed)
Same that


new Thread(task).start();
Async with CompletableFuture
CompletableFuture<Void> voidCF = 

CompletableFuture.runAsync(getLongRunningTaskWithNoResult());

doSomethingElse();

voidCF.get();
/
/
Wait until background task is finished
private static final Executor ASYNC_POOL = USE_COMMON_POOL ?

ForkJoinPool.commonPool() : new ThreadPerTaskExecutor();
Async with CompletableFuture
ExecutorService executorService = Executors.newCachedThreadPool();

executorService
CompletableFuture<Void> voidCF = 

CompletableFuture.runAsync(getLongRunningTaskWithNoResult());

doSomethingElse();

voidCF.get();
/
/
Wait until background task is finished
Async with CompletableFuture
CompletableFuture<Void> voidCF = 

CompletableFuture.runAsync(getLongRunningTaskWithNoResult()

, );

doSomethingElse();

voidCF.get();
/
/
Wait until background task is finished
ExecutorService executorService = Executors.newCachedThreadPool();

executorService
Sized and used for the expected % of CPU used by
your tasks
Async with CompletableFuture
CompletableFuture<Void> voidCF = 

CompletableFuture.runAsync(getLongRunningTaskWithNoResult()

, );

doSomethingElse();

voidCF.get();
/
/
Wait until background task is finished
ExecutorService executorService = Executors.newCachedThreadPool();

executorService
CompletableFuture<Void> voidCF = 

CompletableFuture.runAsync(getLongRunningTaskWithNoResult()

, );

doSomethingElse();

voidCF.get();
/
/
Wait until background task is finished
NoResult()
Async with CompletableFuture
ExecutorService executorService = Executors.newCachedThreadPool();

executorService
CompletableFuture<Void> voidCF = 

CompletableFuture.runAsync(getLongRunningTaskWithNoResult()

, );

doSomethingElse();

voidCF.get();
/
/
Wait until background task is finished
NoResult()
Async with CompletableFuture
ExecutorService executorService = Executors.newCachedThreadPool();

executorService
Result()
CompletableFuture<Void> voidCF = 

CompletableFuture.runAsync(getLongRunningTaskWithNoResult()

, );

doSomethingElse();

voidCF.get();
/
/
Wait until background task is finished
Result()
Async with CompletableFuture
ExecutorService executorService = Executors.newCachedThreadPool();

executorService
CompletableFuture<Void> voidCF = 

CompletableFuture.runAsync(getLongRunningTaskWithNoResult()

, );

doSomethingElse();

voidCF.get();
/
/
Wait until background task is finished
sup Result()
Async with CompletableFuture
ExecutorService executorService = Executors.newCachedThreadPool();

executorService
Void> voidCF =
Async(getLongRunningTaskWithResult()
CompletableFuture<Void> voidCF = 

CompletableFuture.runAsync(getLongRunningTaskWithNoResult()

, );

doSomethingElse();

voidCF.get();
/
/
Wait until background task is finished
sup Async(getLongRunningTaskWithResult()
Async with CompletableFuture
ExecutorService executorService = Executors.newCachedThreadPool();

executorService
Void> voidCF =
ply
CompletableFuture<Void> voidCF = 

CompletableFuture.runAsync(getLongRunningTaskWithNoResult()

, );

doSomethingElse();

result.get();
/
/
Wait until background task is finished
String> result =
sup Async(getLongRunningTaskWithResult()
Async with CompletableFuture
ExecutorService executorService = Executors.newCachedThreadPool();

executorService
ply
CompletableFuture<T>
It may seem just an alternative to Future<T>
public class CompletableFuture<T> 

implements Future<T>, CompletionStage<T>
CompletionStage<T>
@DGOMEZG
CompletionStage<T>
CompletableFuture<T>
Fluent API to chain, compose and combine Futures.
@DGOMEZG
Chaining tasks (blocking)
void invokeSlowProcess() {

Order order = orderService.getOrder();

customerChecker.authorized(order.customer());

}
@DGOMEZG
executed by main in PT7.045928S
invokeSlowServiceDependantTasks();
Chaining tasks with CompletableFuture
@DGOMEZG
CompletableFuture

.supplyAsync(

()
-
>
orderService.getOrder()

).thenAcceptAsync(

order
-
>
customerChecker.authorized(order.customer())

);

Submitted by main in PT0.058982S


Executed by ForkJoinPool.commonPool-worker-1 in PT2.008558S


Executed by ForkJoinPool.commonPool-worker-2 in PT5.010714S
Chaining parallel tasks
@DGOMEZG
Chaining tasks
var orderCF = CompletableFuture.supplyAsync(

()
-
>
orderService.getOrder()

);

orderCF.thenAcceptAsync(

order
-
>
activityTracker.orderAccessed(order)));

orderCF.thenAcceptAsync(

order
-
>
customerChecker.authorized(order.customer())));

@DGOMEZG
Submitted by main in PT0.071653S


getOrder executed by ForkJoinPool.commonPool-worker-1 in PT2.006599S


activityTracker executed by ForkJoinPool.commonPool-worker-3 in PT2.009098S


customerChecker executed by ForkJoinPool.commonPool-worker-2 in PT5.007562S
Chaining multiple parallel tasks
@DGOMEZG
Chaining multiple parallel tasks
@DGOMEZG
var orderCF = CompletableFuture.supplyAsync(

()
-
>
orderService.getOrder()

);

orderCF.thenAcceptAsync(

order
-
>
customerChecker.authorized(order.customer())));

orderWithCF.thenAcceptAsync(order
-
>
{

order.items().stream()

.map(orderItem
-
>


CompletableFuture.supplyAsync( ()
-
>


inventoryService.checkAvailability(

orderItem.productId(), 

orderItem.quantity()))

).collect(Collectors.toList())

.forEach(CompletableFuture
:
:
join);

});
CompletableFuture<T>
Fluent API to chain, compose and combine Futures.
CompletionStage<T>
acceptEither

applyToEither

runAfterEither

runAfterBoth

thenAccept

thenAcceptBoth

thenRun

thenCombine

thenCompose

whenAccept

@DGOMEZG
CompletableFuture


In your API
Why should you consider using CompletableFuture
in you API?
Enable your users to maximise the performance to your queries.


And keep control on how you execute the asynchronous tasks.


Benefit from how other frameworks handle CompletableFutures
(i. e Spring)
@DGOMEZG
Creating and managing CompletableFutures
CompletableFuture<String> completableFuture = 

new CompletableFuture
<
>
();
@DGOMEZG
Creating and managing CompletableFutures
@DGOMEZG
Creating and managing CompletableFutures
@DGOMEZG
@DGOMEZG
An Example: QueryBus at AxonFramework
Queries
UI / API
Commands
Command Model
Projections
Events
An Example: QueryBus at AxonFramework
UI / API
Projections
queryMessage
@DGOMEZG
QueryBus
QueryBusImpl (simplified)
public CompletableFuture<QueryResponseMessage> query(QueryMessage query) {

/
/
Create your CompletableFuture

/
/
Prepare to Run asynchronously

/
/
get Results/Exceptions to complete the future

/
/
return your completableFuture

}
QueryBusImpl (simplified)
public CompletableFuture<QueryResponseMessage> query(QueryMessage query) {

/
/
Create your CompletableFuture

CompletableFuture<QueryResponseMessage> queryTransaction = 

new CompletableFuture
<
>
();

/
/
Prepare to Run asynchronously

/
/
get Results/Exceptions to complete the future

/
/
return your completableFuture

return queryTransaction;

}
QueryBusImpl (simplified)
public CompletableFuture<QueryResponseMessage> query(QueryMessage query) {

CompletableFuture<QueryResponseMessage> queryTransaction = 

new CompletableFuture
<
>
();

try {

/
/
Prepare to Run asynchronously

/
/
get Results to complete the future

} catch (Exception e) {

queryTransaction.completeExceptionally(exception);

}

return queryTransaction;

}
QueryBusImpl (simplified)
public CompletableFuture<QueryResponseMessage> query(QueryMessage query) {

CompletableFuture<QueryResponseMessage> queryTransaction = 

new CompletableFuture
<
>
();

try {

ResultStream<QueryResponse> result =

axonServerConnectionManager.getConnection(targetContext)

.query(query);

/
*
.
.
.
*
/


result.onAvailable(()
-
>


queryTransaction.complete(result.nextIfAvailable())

} catch (Exception e) {

queryTransaction.completeExceptionally(exception);

}

return queryTransaction;

}
Benefits
It allows to compose asynchronous query calls to different systems
@DGOMEZG
private final QueryGateway queryGateway;

@GetMapping("orders/{OrderId}/status")

public Future<OrderStatus> orderStatus(@PathVariable String orderId) {

CompletableFuture<OrderStatus> orderStatusCF =

queryGateway.query(new OrderStatusQuery(orderId),

new InstanceResponseType
<
>
(OrderStatus.class));

/
/
Invoke other external services asynchronously 

/
/
Composing the tasks with CompletionStage.*

/
/
Useful in processes when applying the "Strangling The monolith Pattern”

/
/
Probably not very usual when using DDD 



return orderStatusCF;

}
Benefits
SpringFramework knows how to return a Future<T>


Tomcat (and most application Servers) can handle better the Threads in the ThreadPool
@DGOMEZG
private final QueryGateway queryGateway;

@GetMapping(“orders/{OrderId}/status")

public Future<OrderStatus> orderStatus(@PathVariable String orderId) {

return CompletableFuture<OrderStatus> orderStatusCF =

queryGateway.query(new OrderStatusQuery(orderId),

new InstanceResponseType
<
>
(OrderStatus.class));

}
Conclusions
Conclusions
CompletableFutures are a powerful tool to compose and combine
Asynchronous execution of heterogeneous tasks


Best if used with specific ExecutorService instances, properly sized based
depending on amount of I/O-Wait time


Adding CompletableFutures on you Async API will give more powers to the
developers using your library/framework.
@DGOMEZG
Where do I go from here?
https://github.com/AxonFramework/AxonFramework
Quick Start Tutorial.


https://docs.axoniq.io/reference-guide/getting-started/quick-start
Free Courses on DDD, CQRS, Event-Sourcing


https://academy.axoniq.io/
https:/
/lp.axoniq.io/devnexus-22
The slides
JavaSpecialists newsletter
Java Concurrency Specialist Courses

More Related Content

PDF
3 Kafka patterns to deliver Streaming Machine Learning models with Andrea Spi...
PDF
Introducing the Apache Flink Kubernetes Operator
PPTX
Log4j slideshare
PPTX
Oracle Goldengate for Big Data - LendingClub Implementation
PDF
MongoDB WiredTiger Internals
PPTX
Introduction to GraphQL
PPTX
Express JS
PDF
Operating PostgreSQL at Scale with Kubernetes
3 Kafka patterns to deliver Streaming Machine Learning models with Andrea Spi...
Introducing the Apache Flink Kubernetes Operator
Log4j slideshare
Oracle Goldengate for Big Data - LendingClub Implementation
MongoDB WiredTiger Internals
Introduction to GraphQL
Express JS
Operating PostgreSQL at Scale with Kubernetes

What's hot (20)

PPTX
Google Cloud Dataproc - Easier, faster, more cost-effective Spark and Hadoop
PDF
CDC patterns in Apache Kafka®
PPTX
Introduction to GraphQL Presentation.pptx
PPTX
Mongo DB Presentation
PDF
Monitoring Hadoop with Prometheus (Hadoop User Group Ireland, December 2015)
PDF
Optimizing Delta/Parquet Data Lakes for Apache Spark
PDF
Introduction to Apache Airflow
PDF
Building a Data Pipeline using Apache Airflow (on AWS / GCP)
PPTX
Introduction to snowflake
PDF
The Five Stages of Enterprise Jupyter Deployment
PDF
Best practices for MySQL High Availability Tutorial
PPTX
Real time data viz with Spark Streaming, Kafka and D3.js
PPTX
PDF
Apache Iceberg - A Table Format for Hige Analytic Datasets
PPTX
Java 8 Lambda and Streams
PDF
Greenplum Architecture
PDF
Ingesting and Processing IoT Data - using MQTT, Kafka Connect and KSQL
PDF
PostgreSQL Streaming Replication Cheatsheet
PDF
Building robust CDC pipeline with Apache Hudi and Debezium
PPTX
Cloudera Customer Success Story
Google Cloud Dataproc - Easier, faster, more cost-effective Spark and Hadoop
CDC patterns in Apache Kafka®
Introduction to GraphQL Presentation.pptx
Mongo DB Presentation
Monitoring Hadoop with Prometheus (Hadoop User Group Ireland, December 2015)
Optimizing Delta/Parquet Data Lakes for Apache Spark
Introduction to Apache Airflow
Building a Data Pipeline using Apache Airflow (on AWS / GCP)
Introduction to snowflake
The Five Stages of Enterprise Jupyter Deployment
Best practices for MySQL High Availability Tutorial
Real time data viz with Spark Streaming, Kafka and D3.js
Apache Iceberg - A Table Format for Hige Analytic Datasets
Java 8 Lambda and Streams
Greenplum Architecture
Ingesting and Processing IoT Data - using MQTT, Kafka Connect and KSQL
PostgreSQL Streaming Replication Cheatsheet
Building robust CDC pipeline with Apache Hudi and Debezium
Cloudera Customer Success Story
Ad

Similar to Leverage CompletableFutures to handle async queries. DevNexus 2022 (20)

PDF
Leveraging Completable Futures to handle your query results Asynchrhonously
PDF
Completable future
PDF
The Future of Futures - A Talk About Java 8 CompletableFutures
PPTX
Async java8
ODP
Concurrent Programming in Java
ODP
CompletableFuture
PDF
Asynchronous API in Java8, how to use CompletableFuture
PPTX
Back to the [Completable] Future
PPTX
Java 8 concurrency abstractions
PDF
Java concurrency model - The Future Task
PPTX
Completable Future java 8 Features with example
PDF
Making our Future better
PDF
Asynchronous CompletableFuture Presentation by László-Róbert Albert @Crossover
PPTX
parallel-asynchronous-programming-java.pptx
PPTX
Asynchronous programming using CompletableFutures in Java
PPTX
Fork and join framework
PDF
Paradigma FP y OOP usando técnicas avanzadas de Programación | Programacion A...
PDF
Giorgio zoppi cpp11concurrency
PDF
C++ CoreHard Autumn 2018. Concurrency and Parallelism in C++17 and C++20/23 -...
PPT
Java util concurrent
Leveraging Completable Futures to handle your query results Asynchrhonously
Completable future
The Future of Futures - A Talk About Java 8 CompletableFutures
Async java8
Concurrent Programming in Java
CompletableFuture
Asynchronous API in Java8, how to use CompletableFuture
Back to the [Completable] Future
Java 8 concurrency abstractions
Java concurrency model - The Future Task
Completable Future java 8 Features with example
Making our Future better
Asynchronous CompletableFuture Presentation by László-Róbert Albert @Crossover
parallel-asynchronous-programming-java.pptx
Asynchronous programming using CompletableFutures in Java
Fork and join framework
Paradigma FP y OOP usando técnicas avanzadas de Programación | Programacion A...
Giorgio zoppi cpp11concurrency
C++ CoreHard Autumn 2018. Concurrency and Parallelism in C++17 and C++20/23 -...
Java util concurrent
Ad

More from David Gómez García (20)

PDF
Building Modular monliths that could scale to microservices (only if they nee...
PDF
Building modular monoliths that could scale to microservices (only if they ne...
PDF
Builiding Modular monoliths that can scale to microservices. JBCNConf 2021
PDF
Cdm mil-18 - hypermedia ap is for headless platforms and data integration
PDF
What's in a community like Liferay's
PDF
Java9 Beyond Modularity - Java 9 más allá de la modularidad
PDF
T3chFest2016 - Uso del API JavaScript de Photoshop para obtener fotos HDTR
PDF
Managing user's data with Spring Session
PDF
Parallel streams in java 8
PDF
Construccion de proyectos con gradle
PDF
Java 8 Stream API. A different way to process collections.
PDF
Midiendo la calidad de código en WTF/Min (Revisado EUI Abril 2014)
PDF
Measuring Code Quality in WTF/min.
PDF
Spring4 whats up doc?
PDF
Gradle como alternativa a maven
PDF
El poder del creador de Software. Entre la ingeniería y la artesanía
PDF
Geo-SentimentZ
PDF
HDTR images with Photoshop Javascript Scripting
PDF
Wtf per lineofcode
PDF
A real systemwithjms-rest-protobuf-mongodb
Building Modular monliths that could scale to microservices (only if they nee...
Building modular monoliths that could scale to microservices (only if they ne...
Builiding Modular monoliths that can scale to microservices. JBCNConf 2021
Cdm mil-18 - hypermedia ap is for headless platforms and data integration
What's in a community like Liferay's
Java9 Beyond Modularity - Java 9 más allá de la modularidad
T3chFest2016 - Uso del API JavaScript de Photoshop para obtener fotos HDTR
Managing user's data with Spring Session
Parallel streams in java 8
Construccion de proyectos con gradle
Java 8 Stream API. A different way to process collections.
Midiendo la calidad de código en WTF/Min (Revisado EUI Abril 2014)
Measuring Code Quality in WTF/min.
Spring4 whats up doc?
Gradle como alternativa a maven
El poder del creador de Software. Entre la ingeniería y la artesanía
Geo-SentimentZ
HDTR images with Photoshop Javascript Scripting
Wtf per lineofcode
A real systemwithjms-rest-protobuf-mongodb

Recently uploaded (20)

PPTX
Lecture 3: Operating Systems Introduction to Computer Hardware Systems
PDF
Odoo Companies in India – Driving Business Transformation.pdf
PPTX
history of c programming in notes for students .pptx
PDF
Design an Analysis of Algorithms I-SECS-1021-03
PDF
System and Network Administration Chapter 2
PDF
Internet Downloader Manager (IDM) Crack 6.42 Build 41
PDF
Softaken Excel to vCard Converter Software.pdf
PDF
Adobe Premiere Pro 2025 (v24.5.0.057) Crack free
PDF
How to Migrate SBCGlobal Email to Yahoo Easily
PPTX
Essential Infomation Tech presentation.pptx
PPTX
Agentic AI : A Practical Guide. Undersating, Implementing and Scaling Autono...
PPTX
Odoo POS Development Services by CandidRoot Solutions
PPTX
L1 - Introduction to python Backend.pptx
PDF
Internet Downloader Manager (IDM) Crack 6.42 Build 42 Updates Latest 2025
PPTX
ai tools demonstartion for schools and inter college
PDF
Wondershare Filmora 15 Crack With Activation Key [2025
PDF
SAP S4 Hana Brochure 3 (PTS SYSTEMS AND SOLUTIONS)
PDF
System and Network Administraation Chapter 3
PDF
Raksha Bandhan Grocery Pricing Trends in India 2025.pdf
PDF
Why TechBuilder is the Future of Pickup and Delivery App Development (1).pdf
Lecture 3: Operating Systems Introduction to Computer Hardware Systems
Odoo Companies in India – Driving Business Transformation.pdf
history of c programming in notes for students .pptx
Design an Analysis of Algorithms I-SECS-1021-03
System and Network Administration Chapter 2
Internet Downloader Manager (IDM) Crack 6.42 Build 41
Softaken Excel to vCard Converter Software.pdf
Adobe Premiere Pro 2025 (v24.5.0.057) Crack free
How to Migrate SBCGlobal Email to Yahoo Easily
Essential Infomation Tech presentation.pptx
Agentic AI : A Practical Guide. Undersating, Implementing and Scaling Autono...
Odoo POS Development Services by CandidRoot Solutions
L1 - Introduction to python Backend.pptx
Internet Downloader Manager (IDM) Crack 6.42 Build 42 Updates Latest 2025
ai tools demonstartion for schools and inter college
Wondershare Filmora 15 Crack With Activation Key [2025
SAP S4 Hana Brochure 3 (PTS SYSTEMS AND SOLUTIONS)
System and Network Administraation Chapter 3
Raksha Bandhan Grocery Pricing Trends in India 2025.pdf
Why TechBuilder is the Future of Pickup and Delivery App Development (1).pdf

Leverage CompletableFutures to handle async queries. DevNexus 2022

  • 1. Leveraging CompletableFutures to handle your query results asynchronously David Gómez G. Developer Advocate
  • 3. Same type of tasks Workload split between similar workers Have the work finished before Parallelism Concurrency Different type of tasks Usually do some works while waiting for other tasks to be completed. Have the work finished before @DGOMEZG
  • 5. Lots of tools since Java 1 Java has (basic) building blocks for Concurrency and parallelism since Java 1. Even when most desktop computers were single-core @DGOMEZG
  • 6. Threads Very Expensive Thread t = new Thread(task); t.start(); t.join(); Easily forgotten Blocking call
  • 12. Since Java 5 Concurrency & parallelism support improved in Java 5 Lots of New Concurrency constructors New concurrent-friendly Data Structures Revisited and improved in Java 7, 8, 9 … More coming up as part of loom project @DGOMEZG
  • 14. ExecutorService And now we can submit: - tasks that do not return anything. Runnable - tasks that return a result. Callable<R> Executor Service returns a Future<R> @DGOMEZG
  • 15. ExecutorService & Future<T> ExecutorService executorService = Executors.newCachedThreadPool(); Future<String> taskResult = executorService.submit(longRunningTaskWithResult); String s = taskResult.get(); Blocking call
  • 16. ExecutorService & Future<T> ExecutorService executorService = Executors.newCachedThreadPool(); Future<String> taskResult = executorService.submit(longRunningTaskWithResult); while (!taskResult.isDone()) { doSomethingElse(); } String s = taskResult.get(); False while task is not cancelled nor fi nished Improving performance by doing other tasks.
  • 17. Running Multiple T asks List<Future<String > > taskResults = new ArrayList < > (); for (Callable<String> task : tasks) { taskResults.add(executorService.submit(task)); } for (Future<String> result : taskResults) { processResult(result.get()); } Bene fi t only between submitting all tasks and getting the results
  • 18. Running Heterogeneous T asks List<Future<String > > taskResults = new ArrayList < > (); for (Callable<String> task : tasks) { taskResults.add(executorService.submit(task)); } for (Future<String> result : taskResults) { processResult(result.get()); } What if task1 is too slow while task2 is fast? What if we need the result of task1 to submit task2? (CompletionService returns tasks in the order they are fi nished)
  • 20. CompletableFuture<T> Introduced in Java8 Has specific methods to submit tasks to an ExecutorService Implements a fluent API (CompletionStage) that allows chaining and combining dependant tasks. Allow to use different sized ExecutorServices for different tasks. @DGOMEZG
  • 22. Async with CompletableFuture CompletableFuture<Void> voidCF = CompletableFuture.runAsync(getLongRunningTaskWithNoResult()); doSomethingElse();
  • 23. Async with CompletableFuture CompletableFuture<Void> voidCF = CompletableFuture.runAsync(getLongRunningTaskWithNoResult()); doSomethingElse(); CompletableFuture<Void> voidCF = CompletableFuture.runAsync(getLongRunningTaskWithNoResult()); doSomethingElse(); voidCF.get(); / / Wait until background task is finished
  • 24. Async with CompletableFuture CompletableFuture<Void> voidCF = CompletableFuture.runAsync(getLongRunningTaskWithNoResult()); doSomethingElse(); voidCF.get(); / / Wait until background task is finished private static final Executor ASYNC_POOL = USE_COMMON_POOL ? ForkJoinPool.commonPool() : new ThreadPerTaskExecutor();
  • 25. Async with CompletableFuture private static final Executor ASYNC_POOL = USE_COMMON_POOL ? ForkJoinPool.commonPool() : new ThreadPerTaskExecutor(); Shared with the JVM (may affect parallel streams) Sized for CPU intensive tasks (if our task is IO bound, we may affect app performance) Daemon Threads (if our main thread finishes, tasks may not be executed) Same that new Thread(task).start();
  • 26. Async with CompletableFuture CompletableFuture<Void> voidCF = CompletableFuture.runAsync(getLongRunningTaskWithNoResult()); doSomethingElse(); voidCF.get(); / / Wait until background task is finished private static final Executor ASYNC_POOL = USE_COMMON_POOL ? ForkJoinPool.commonPool() : new ThreadPerTaskExecutor();
  • 27. Async with CompletableFuture ExecutorService executorService = Executors.newCachedThreadPool(); executorService CompletableFuture<Void> voidCF = CompletableFuture.runAsync(getLongRunningTaskWithNoResult()); doSomethingElse(); voidCF.get(); / / Wait until background task is finished
  • 28. Async with CompletableFuture CompletableFuture<Void> voidCF = CompletableFuture.runAsync(getLongRunningTaskWithNoResult() , ); doSomethingElse(); voidCF.get(); / / Wait until background task is finished ExecutorService executorService = Executors.newCachedThreadPool(); executorService Sized and used for the expected % of CPU used by your tasks
  • 29. Async with CompletableFuture CompletableFuture<Void> voidCF = CompletableFuture.runAsync(getLongRunningTaskWithNoResult() , ); doSomethingElse(); voidCF.get(); / / Wait until background task is finished ExecutorService executorService = Executors.newCachedThreadPool(); executorService
  • 30. CompletableFuture<Void> voidCF = CompletableFuture.runAsync(getLongRunningTaskWithNoResult() , ); doSomethingElse(); voidCF.get(); / / Wait until background task is finished NoResult() Async with CompletableFuture ExecutorService executorService = Executors.newCachedThreadPool(); executorService
  • 31. CompletableFuture<Void> voidCF = CompletableFuture.runAsync(getLongRunningTaskWithNoResult() , ); doSomethingElse(); voidCF.get(); / / Wait until background task is finished NoResult() Async with CompletableFuture ExecutorService executorService = Executors.newCachedThreadPool(); executorService Result()
  • 32. CompletableFuture<Void> voidCF = CompletableFuture.runAsync(getLongRunningTaskWithNoResult() , ); doSomethingElse(); voidCF.get(); / / Wait until background task is finished Result() Async with CompletableFuture ExecutorService executorService = Executors.newCachedThreadPool(); executorService
  • 33. CompletableFuture<Void> voidCF = CompletableFuture.runAsync(getLongRunningTaskWithNoResult() , ); doSomethingElse(); voidCF.get(); / / Wait until background task is finished sup Result() Async with CompletableFuture ExecutorService executorService = Executors.newCachedThreadPool(); executorService Void> voidCF = Async(getLongRunningTaskWithResult()
  • 34. CompletableFuture<Void> voidCF = CompletableFuture.runAsync(getLongRunningTaskWithNoResult() , ); doSomethingElse(); voidCF.get(); / / Wait until background task is finished sup Async(getLongRunningTaskWithResult() Async with CompletableFuture ExecutorService executorService = Executors.newCachedThreadPool(); executorService Void> voidCF = ply
  • 35. CompletableFuture<Void> voidCF = CompletableFuture.runAsync(getLongRunningTaskWithNoResult() , ); doSomethingElse(); result.get(); / / Wait until background task is finished String> result = sup Async(getLongRunningTaskWithResult() Async with CompletableFuture ExecutorService executorService = Executors.newCachedThreadPool(); executorService ply
  • 36. CompletableFuture<T> It may seem just an alternative to Future<T> public class CompletableFuture<T> implements Future<T>, CompletionStage<T> CompletionStage<T> @DGOMEZG
  • 37. CompletionStage<T> CompletableFuture<T> Fluent API to chain, compose and combine Futures. @DGOMEZG
  • 38. Chaining tasks (blocking) void invokeSlowProcess() { Order order = orderService.getOrder(); customerChecker.authorized(order.customer()); } @DGOMEZG executed by main in PT7.045928S invokeSlowServiceDependantTasks();
  • 39. Chaining tasks with CompletableFuture @DGOMEZG CompletableFuture .supplyAsync( () - > orderService.getOrder() ).thenAcceptAsync( order - > customerChecker.authorized(order.customer()) ); Submitted by main in PT0.058982S Executed by ForkJoinPool.commonPool-worker-1 in PT2.008558S Executed by ForkJoinPool.commonPool-worker-2 in PT5.010714S
  • 41. Chaining tasks var orderCF = CompletableFuture.supplyAsync( () - > orderService.getOrder() ); orderCF.thenAcceptAsync( order - > activityTracker.orderAccessed(order))); orderCF.thenAcceptAsync( order - > customerChecker.authorized(order.customer()))); @DGOMEZG Submitted by main in PT0.071653S getOrder executed by ForkJoinPool.commonPool-worker-1 in PT2.006599S activityTracker executed by ForkJoinPool.commonPool-worker-3 in PT2.009098S customerChecker executed by ForkJoinPool.commonPool-worker-2 in PT5.007562S
  • 42. Chaining multiple parallel tasks @DGOMEZG
  • 43. Chaining multiple parallel tasks @DGOMEZG var orderCF = CompletableFuture.supplyAsync( () - > orderService.getOrder() ); orderCF.thenAcceptAsync( order - > customerChecker.authorized(order.customer()))); orderWithCF.thenAcceptAsync(order - > { order.items().stream() .map(orderItem - > CompletableFuture.supplyAsync( () - > inventoryService.checkAvailability( orderItem.productId(), orderItem.quantity())) ).collect(Collectors.toList()) .forEach(CompletableFuture : : join); });
  • 44. CompletableFuture<T> Fluent API to chain, compose and combine Futures. CompletionStage<T> acceptEither applyToEither runAfterEither runAfterBoth thenAccept thenAcceptBoth thenRun thenCombine thenCompose whenAccept @DGOMEZG
  • 46. Why should you consider using CompletableFuture in you API? Enable your users to maximise the performance to your queries. And keep control on how you execute the asynchronous tasks. Benefit from how other frameworks handle CompletableFutures (i. e Spring) @DGOMEZG
  • 47. Creating and managing CompletableFutures CompletableFuture<String> completableFuture = new CompletableFuture < > (); @DGOMEZG
  • 48. Creating and managing CompletableFutures @DGOMEZG
  • 49. Creating and managing CompletableFutures @DGOMEZG
  • 50. @DGOMEZG An Example: QueryBus at AxonFramework Queries UI / API Commands Command Model Projections Events
  • 51. An Example: QueryBus at AxonFramework UI / API Projections queryMessage @DGOMEZG QueryBus
  • 52. QueryBusImpl (simplified) public CompletableFuture<QueryResponseMessage> query(QueryMessage query) { / / Create your CompletableFuture / / Prepare to Run asynchronously / / get Results/Exceptions to complete the future / / return your completableFuture }
  • 53. QueryBusImpl (simplified) public CompletableFuture<QueryResponseMessage> query(QueryMessage query) { / / Create your CompletableFuture CompletableFuture<QueryResponseMessage> queryTransaction = new CompletableFuture < > (); / / Prepare to Run asynchronously / / get Results/Exceptions to complete the future / / return your completableFuture return queryTransaction; }
  • 54. QueryBusImpl (simplified) public CompletableFuture<QueryResponseMessage> query(QueryMessage query) { CompletableFuture<QueryResponseMessage> queryTransaction = new CompletableFuture < > (); try { / / Prepare to Run asynchronously / / get Results to complete the future } catch (Exception e) { queryTransaction.completeExceptionally(exception); } return queryTransaction; }
  • 55. QueryBusImpl (simplified) public CompletableFuture<QueryResponseMessage> query(QueryMessage query) { CompletableFuture<QueryResponseMessage> queryTransaction = new CompletableFuture < > (); try { ResultStream<QueryResponse> result = axonServerConnectionManager.getConnection(targetContext) .query(query); / * . . . * / result.onAvailable(() - > queryTransaction.complete(result.nextIfAvailable()) } catch (Exception e) { queryTransaction.completeExceptionally(exception); } return queryTransaction; }
  • 56. Benefits It allows to compose asynchronous query calls to different systems @DGOMEZG private final QueryGateway queryGateway; @GetMapping("orders/{OrderId}/status") public Future<OrderStatus> orderStatus(@PathVariable String orderId) { CompletableFuture<OrderStatus> orderStatusCF = queryGateway.query(new OrderStatusQuery(orderId), new InstanceResponseType < > (OrderStatus.class)); / / Invoke other external services asynchronously / / Composing the tasks with CompletionStage.* / / Useful in processes when applying the "Strangling The monolith Pattern” / / Probably not very usual when using DDD return orderStatusCF; }
  • 57. Benefits SpringFramework knows how to return a Future<T> Tomcat (and most application Servers) can handle better the Threads in the ThreadPool @DGOMEZG private final QueryGateway queryGateway; @GetMapping(“orders/{OrderId}/status") public Future<OrderStatus> orderStatus(@PathVariable String orderId) { return CompletableFuture<OrderStatus> orderStatusCF = queryGateway.query(new OrderStatusQuery(orderId), new InstanceResponseType < > (OrderStatus.class)); }
  • 59. Conclusions CompletableFutures are a powerful tool to compose and combine Asynchronous execution of heterogeneous tasks Best if used with specific ExecutorService instances, properly sized based depending on amount of I/O-Wait time Adding CompletableFutures on you Async API will give more powers to the developers using your library/framework. @DGOMEZG
  • 60. Where do I go from here? https://github.com/AxonFramework/AxonFramework Quick Start Tutorial. 
 https://docs.axoniq.io/reference-guide/getting-started/quick-start Free Courses on DDD, CQRS, Event-Sourcing 
 https://academy.axoniq.io/ https:/ /lp.axoniq.io/devnexus-22 The slides JavaSpecialists newsletter Java Concurrency Specialist Courses