Need to confirm something. The following code:
CompletableFuture
.supplyAsync(() -> {return doSomethingAndReturnA();})
.thenApply(a -> convertToB(a));
would be the same as:
CompletableFuture
.supplyAsync(() -> {
A a = doSomethingAndReturnA();
convertToB(a);
});
Right?
Furthermore, another two questions following as for "is there any reason why we would use thenApply
?"
1) having big code for conversion?
or
2) need to reuse the lambda block in other places?
It is not the same thing. In the second example where thenApply
is not used it is certain that the call to convertToB
is executed in the same thread as the method doSomethingAndReturnA
.
But, in the first example when the thenApply
method is used other things can happen.
First of all, if the CompletableFuture
that executes the doSomethingAndReturnA
has completed, the invocation of the thenApply
will happen in the caller thread. If the CompletableFutures
hasn't been completed the Function
passed to thenApply
will be invoked in the same thread as doSomethingAndReturnA
.
Confusing? Well this article might be helpful (thanks @SotiriosDelimanolis for the link).
I have provided a short example that illustrates how thenApply
works.
public class CompletableTest {
public static void main(String... args) throws ExecutionException, InterruptedException {
final CompletableFuture<Integer> future = CompletableFuture
.supplyAsync(() -> doSomethingAndReturnA())
.thenApply(a -> convertToB(a));
future.get();
}
private static int convertToB(final String a) {
System.out.println("convertToB: " + Thread.currentThread().getName());
return Integer.parseInt(a);
}
private static String doSomethingAndReturnA() {
System.out.println("doSomethingAndReturnA: " + Thread.currentThread().getName());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "1";
}
}
And the output is:
doSomethingAndReturnA: ForkJoinPool.commonPool-worker-1
convertToB: ForkJoinPool.commonPool-worker-1
So, when the first operation is slow (i.e. the CompletableFuture
is not yet completed) both calls occur in the same thread. But if the we were to remove the Thread.sleep
-call from the doSomethingAndReturnA
the output (may) be like this:
doSomethingAndReturnA: ForkJoinPool.commonPool-worker-1
convertToB: main
Note that convertToB
call is in the main
thread.