Given this piece of code:
public List<String> findPrices(String product){
List<CompletableFuture<String>> priceFutures =
shops.stream()
.map(shop -> CompletableFuture.supplyAsync(
() -> shop.getPrice(product), executor))
.map(future -> future.thenApply(Quote::parse))
.map(future -> future.thenCompose(quote ->
CompletableFuture.supplyAsync(
() -> Discount.applyDiscount(quote), executor
)))
.collect(toList());
return priceFutures.stream()
.map(CompletableFuture::join)
.collect(toList());
}
This part of it:
.map(future -> future.thenCompose(quote ->
CompletableFuture.supplyAsync(
() -> Discount.applyDiscount(quote), executor
)))
Could it be rewrite as:
.map(future ->
future.thenComposeAsync(quote -> Discount.applyDiscount(quote), executor))
I took this code from an example of a book and says the two solutions are different, but I do not understand why.
Let's consider a function that looks like this:
The difference will be with respect to which thread
generateRequest()
gets called on.thenCompose
will callgenerateRequest()
on the same thread as the upstream task (or the calling thread if the upstream task has already completed).thenComposeAsync
will callgenerateRequest()
on the provided executor if provided, or on the defaultForkJoinPool
otherwise.