Java Reference
In-Depth Information
Well done! It looks like this was a simple but very effective idea: now the four different shops are
queried in parallel, so it takes in total just a bit more than a second to complete. Can you do even
better? Let's try to turn all the synchronous invocations to the different shops in the findPrices
method into asynchronous invocations, using what you learned so far about
CompletableFutures.
11.3.2. Making asynchronous requests with CompletableFutures
You saw that you can use the factory method supplyAsync to create Completable-Future objects.
Let's use it:
List<CompletableFuture<String>> priceFutures =
shops.stream()
.map(shop -> CompletableFuture.supplyAsync(
() -> String.format("%s price is %.2f",
shop.getName(), shop.getPrice(product))))
.collect(toList());
Using this approach, you obtain a List<CompletableFuture<String>>, where each
CompletableFuture in the List will contain the String name of a shop when its computation is
completed. But because the findPrices method you're trying to reimplement using
CompletableFutures has to return just a List<String>, you'll have to wait for the completion of
all these futures and extract the value they contain before returning the List.
To achieve this result, you can apply a second map operation to the original
List<CompletableFuture<String>>, invoking a join on all the futures in the List and then
waiting for their completion one by one. Note that the join method of the CompletableFuture
class has the same meaning as the get method also declared in the Future interface, with the
only difference being that join doesn't throw any checked exception. By using it you don't have
to bloat the lambda expression passed to this second map with a try/catch block. Putting
everything together, you can rewrite the findPrices method as follows.
 
Search WWH ::




Custom Search