Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
919 views
in Technique[技术] by (71.8m points)

multithreading - CompletableFuture, supplyAsync() and thenApply()

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?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...