首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >CompletableFuture.supplyAsync与新CompletableFuture()

CompletableFuture.supplyAsync与新CompletableFuture()
EN

Stack Overflow用户
提问于 2018-02-21 12:57:46
回答 2查看 2.8K关注 0票数 2

我不明白CompletableFuture/supplyAsync在这里发生了什么。

如果我从以前实例化的supplyAsync对象调用CompletableFuture方法,它永远不会完成:

代码语言:javascript
复制
public static void ex1() throws ExecutionException, InterruptedException {
   final CompletableFuture<String> cf = new CompletableFuture<>();
   cf.supplyAsync(() -> {
      System.out.println("Main.m3");
      return "Main";
   });
   System.out.println("Start: cf = " + cf);
   final String value = cf.get();
   System.out.println("End: value = " + value);
}

这是输出:

代码语言:javascript
复制
Start: cf = java.util.concurrent.CompletableFuture@5b480cf9[Not completed]
Main.m3

如您所见,System.out.println("End: cf = " + cf);从未被执行过。

为了使它运行,我需要将一个complete(my value)放在supplyAsync的主体中。

但是--如果我在创建CompletableFuture时直接调用supplyAsync (或者通过调用静态CompletableFuture.supplyAsync):

代码语言:javascript
复制
public static void ex2() throws ExecutionException, InterruptedException {
   final CompletableFuture<String> cf = new CompletableFuture<>()
      .supplyAsync(() -> {
         System.out.println("Main.m3");
         return "Main";
      });
   System.out.println("Start: cf = " + cf);
   final String value = cf.get();
   System.out.println("End: value = " + value);
}

它如预期的那样工作。您可以在这里看到输出:

代码语言:javascript
复制
Start: cf = java.util.concurrent.CompletableFuture@5b480cf9[Not completed]
Main.m3
End: value = Main

所以我的问题是:为什么?我遗漏了什么吗?

EN

回答 2

Stack Overflow用户

发布于 2018-02-21 13:19:51

supplyAsync是一个返回新CompletableFuturestatic方法,不应该通过实例调用它。

first case中,您在一个从未启动CompletableFuture上调用get()

实际上,您会注意到,当调用ex1()时,您的程序将永远处于pending状态。因此,它永远无法执行下一行,它打印结果Main (并行计算的其他Future的结果)。

重点是,您不将第二个CompletableFuture存储在任何地方。因此,您不可能调用正确的 get()

第二个案例中,您正在使用supplyAsync的返回值构建实例,并将其存储在cf中。这是构造CompletableFuture的正确方法。( new CompletableFuture<>()部分是多余的;实际上,您可以立即用supplyAsync为它分配一个新实例)。

因此,当您调用get()时,您将等待正确的CompletableFuture返回其结果。

票数 4
EN

Stack Overflow用户

发布于 2018-02-21 13:19:09

java.util.concurrent.CompletableFuture#supplyAsync(java.util.function.Supplier<U>)是一个静态函数,所以在ex1中,您要分配一个CompletableFuture,但从不使用它。

来自java 8源:

代码语言:javascript
复制
/**
 * Returns a new CompletableFuture that is asynchronously completed
 * by a task running in the {@link ForkJoinPool#commonPool()} with
 * the value obtained by calling the given Supplier.
 *
 * @param supplier a function returning the value to be used
 * to complete the returned CompletableFuture
 * @param <U> the function's return type
 * @return the new CompletableFuture
 */
public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier) {
    return asyncSupplyStage(ASYNC_POOL, supplier);
}

就您的情况而言,ex1应该是:

代码语言:javascript
复制
public static void ex1() throws ExecutionException, InterruptedException {
    CompletableFuture<String> cf = CompletableFuture.supplyAsync(() -> {
        System.out.println("Main.m3");
        return "Main";
    });
    System.out.println("Start: cf = " + cf);
    final String value = cf.get();
    System.out.println("End: value = " + value);
}

ex2是正确的格式,但是通过分配一个新的CompletableFuture并调用一个静态方法,您可以意外地达到这个目的,但是在ex2中,您不会放弃返回的值,而在ex1中则会这样做。

在您的ex1和ex2中,您实际上是在调用相同的方法,对于使用类名正确调用静态并且不丢弃返回对象的两种情况,我为ex1提供的代码都是正确的。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/48906538

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档