CompletableFuture,supplyAsync()和thenApply()

igr*_*igr 39 futuretask java-8

需要确认一下.以下代码:

CompletableFuture
    .supplyAsync(() -> {return doSomethingAndReturnA();})
    .thenApply(a -> convertToB(a));
Run Code Online (Sandbox Code Playgroud)

会是这样的:

CompletableFuture
    .supplyAsync(() -> {
        A a = doSomethingAndReturnA();
        convertToB(a);
 });
Run Code Online (Sandbox Code Playgroud)

对?

此外,另外两个问题是"我们有什么理由使用thenApply?"

1)有大转换代码?

要么

2)需要在其他地方重用lambda块吗?

was*_*ren 56

不是一回事.在thenApply未使用的第二个示例中,确定调用convertToB是在与方法相同的线程中执行的doSomethingAndReturnA.

但是,在thenApply使用该方法的第一个示例中,可能会发生其他事情.

首先,如果CompletableFuture执行doSomethingAndReturnA完成,则调用thenApply将在调用者线程中进行.如果CompletableFutures尚未完成Function传递的thenApply将在同一个线程中调用doSomethingAndReturnA.

混乱?那么这篇文章可能会有所帮助(感谢@SotiriosDelimanolis的链接).

我提供了一个简短的例子,说明了如何thenApply运作.

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";
    }
}
Run Code Online (Sandbox Code Playgroud)

输出是:

doSomethingAndReturnA: ForkJoinPool.commonPool-worker-1
convertToB: ForkJoinPool.commonPool-worker-1
Run Code Online (Sandbox Code Playgroud)

因此,当第一个操作很慢(即CompletableFuture尚未完成)时,两个调用都发生在同一个线程中.但是如果我们Thread.sleep要从doSomethingAndReturnA输出中删除-call (可能)就像这样:

doSomethingAndReturnA: ForkJoinPool.commonPool-worker-1
convertToB: main
Run Code Online (Sandbox Code Playgroud)

请注意,convertToB调用是在main线程中.