How to run combined CompletableFutures asynchronously

Viewed 531

I want to load data on the application startup by calling different services which returns lists of different object types. Each service calls DAO class to read some data. So I have created individual CompletableFuture like:

CompletableFuture<List<DTO1> future1 = CompletableFuture.supplyAsync(() -> service1.callMethod1());
CompletableFuture<List<DTO2> future2 = CompletableFuture.supplyAsync(() -> service2.callMethod2());
CompletableFuture<List<DTO3> future3 = CompletableFuture.supplyAsync(() -> service3.callMethod3());

and combined them like:

CompletableFuture<Void> combinedFuture = CompletableFuture.allOf(future1, future2, future3);

If I do something like:

combinedFuture.thenRunAsync(()->future1.join(), future2.join(), future3.join())

Then I am getting the compile time error. I am new to the Java 8 concurrency features such as CompletableFuture, I thought calling thenRunAsync will run each future1,future2,future3 in different threads. Is it correct way to do it by calling thenRunAsync? If Yes, then how to remove that compile time error?

But if I do something like:

Stream.of(future1, future2, future3)
        .map(CompletableFuture::join)
        .collect(Collectors.toList());

It is returning List<? extends List<?>> then It seems to work but should I call .collect(Collectors.toList()) ? I am not concerned about this combined result as each of the individual method calls are already annotated with @Cacheable for caching purposes. Also, If I do something like:

Stream.of(future1, future2, future3)
        .foreach(CompletableFuture::join);

will it run each future1,future2,future3 in different threads? How can I run future1,future2,future3 in 3 different threads? Is there any correct way to run these three database calls asynchronously?

1 Answers
CompletableFuture<List<DTO1> future1 = CompletableFuture.supplyAsync(() -> service1.callMethod1());
CompletableFuture<List<DTO2> future2 = CompletableFuture.supplyAsync(() -> service2.callMethod2());
CompletableFuture<List<DTO3> future3 = CompletableFuture.supplyAsync(() -> service3.callMethod3());

This code is already instructing all three futures to run on different threads (assuming that there are at least 3 threads in the common pool). Calling join() on one of them simply instructs the calling thread to block on completion of that task, and doesn't change the fact that the 3 calls are proceeding in parallel. All of your solutions that compile are reasonable.

Related