53

需要确认一些东西。以下代码:

CompletableFuture
    .supplyAsync(() -> {return doSomethingAndReturnA();})
    .thenApply(a -> convertToB(a));

将与以下内容相同:

CompletableFuture
    .supplyAsync(() -> {
        A a = doSomethingAndReturnA();
        convertToB(a);
 });

对?

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

1)有大代码进行转换?

或者

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

4

2 回答 2

72

不是一回事。在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";
    }
}

输出是:

doSomethingAndReturnA: ForkJoinPool.commonPool-worker-1
convertToB: ForkJoinPool.commonPool-worker-1

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

doSomethingAndReturnA: ForkJoinPool.commonPool-worker-1
convertToB: main

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

于 2014-12-31T16:52:10.453 回答
3

thenApply()supplyAsync()是一个回调函数,返回值时会执行。

在代码片段 2 中,调用的线程doSomethingAndReturnA()等待函数执行并返回数据。

但是在一些特殊情况下(比如调用Webservice,等待响应),线程要等待很长时间才能得到响应,这严重消耗了大量的系统计算资源(只是等待响应)。

为了避免这种情况,CompletableFuture带有回调功能,一旦doSomethingAndReturnA()调用,一个单独的线程将负责执行doSomethingAndReturnA(),主调用者​​线程将继续执行其他操作,而无需等待响应返回。

一旦 的响应doSomethingAndReturnA可用,将调用回调方法(即thenApply()

于 2017-09-14T12:55:09.727 回答