CompletableFuture,supplyAsync()和thenApply()

时间:2014-12-31 16:12:59

标签: java-8 futuretask

需要确认一些事情。以下代码:

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

与:

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

右?

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

1)拥有大量的转换代码?

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

2 个答案:

答案 0 :(得分:54)

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

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

首先,如果执行CompletableFuture的{​​{1}}已完成,则doSomethingAndReturnA的调用将在调用者线程中发生。如果thenApply尚未完成,则会在与CompletableFutures相同的帖子中调用传递给Function的{​​{1}}。

混淆?那么this article might be helpful(感谢@SotiriosDelimanolis的链接)。

我提供了一个简短的示例,说明了thenApply的工作原理。

doSomethingAndReturnA

输出是:

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

请注意,doSomethingAndReturnA调用位于doSomethingAndReturnA: ForkJoinPool.commonPool-worker-1 convertToB: main 主题。

答案 1 :(得分:2)

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

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

但在某些特殊情况下(比如进行Webservice调用和等待响应),线程必须等待 long 时间才能获得响应,这会严重占用大量系统计算资源(只需等待回应)。

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

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