简体   繁体   English

CompletableFuture.supplyAsync与新的CompletableFuture()

[英]CompletableFuture.supplyAsync vs new CompletableFuture()

I don't understand what's happening here with CompletableFuture/supplyAsync. 我不明白CompletableFuture / supplyAsync在这里发生了什么。

If I invoke the supplyAsync method from a CompletableFuture object previously instantiated, it never completes: 如果我从先前实例化的CompletableFuture对象中调用supplyAsync方法,它将永远不会完成:

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);
}

This is the output: 这是输出:

Start: cf = java.util.concurrent.CompletableFuture@5b480cf9[Not completed]
Main.m3

As you can see the System.out.println("End: cf = " + cf); 如您所见, System.out.println("End: cf = " + cf); is never executed. 永远不会执行。

To make it running I need to put a complete(my value) inside the body of the supplyAsync. 为了使其运行,我需要将一个complete(my value)放在supplyAsync的主体内。

But if I directly invoke the supplyAsync while creating the CompletableFuture (or by calling the static CompletableFuture.supplyAsync ): 但是,如果我在创建CompletableFuture时直接调用supplyAsync (或通过调用静态CompletableFuture.supplyAsync ):

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);
}

It works as expected. 它按预期工作。 You can see here the output: 您可以在此处看到输出:

Start: cf = java.util.concurrent.CompletableFuture@5b480cf9[Not completed]
Main.m3
End: value = Main

So my question is: why this? 所以我的问题是:为什么这样? Is there something I am missing? 我有什么想念的吗?

supplyAsync is a static method that returns a new CompletableFuture and it should not be called via an instance. supplyAsync是一个static方法,它返回一个新的CompletableFuture ,不应通过实例调用它。

In the first case , you are calling get() on a CompletableFuture that never started anything. 在第一种情况下 ,您正在从未启动任何东西的CompletableFuture上调用get()

In fact, you'll notice that your program when calling ex1() will remain in a pending state forever. 实际上,您会注意到,调用ex1()时,程序将永远保持pending状态。 And because of this, it can never execute the next line, which prints the result Main (of the other Future that computed in parallel). 因此,它永远无法执行下一行,该行将打印结果Main (另一个并行计算的Future的结果)。

The point, is that you do not store the second CompletableFuture anywhere. 关键是您不要在任何地方存储第二个CompletableFuture So there is no way you'll be able to call the correct get() . 因此,您将无法调用正确的 get()


In your second case you are building the instance with the return value of supplyAsync , and you store it in cf . 第二个情况下 ,你都建设有返回值的情况下supplyAsync ,你将它存储在cf And this is the right way to construct a CompletableFuture . 这是构造CompletableFuture的正确方法。 (the new CompletableFuture<>() part is superfluous; in fact, you assign it a new instance right away with supplyAsync ). new CompletableFuture<>()部分是多余的;实际上,您可以通过supplyAsync为其分配一个新实例)。

When you call get() you therefore wait for the right CompletableFuture to return its result. 因此,当您调用get()您将等待正确的CompletableFuture返回其结果。

java.util.concurrent.CompletableFuture#supplyAsync(java.util.function.Supplier<U>) is a static function, so in ex1 you are allocating a CompletableFuture but never using it. java.util.concurrent.CompletableFuture#supplyAsync(java.util.function.Supplier<U>)是一个静态函数,因此在ex1中,您分配了CompletableFuture但从未使用过。

From java 8 source: 从Java 8来源:

/**
 * 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);
}

in your case ex1 should be: 在您的情况下,ex1应该是:

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);
}

and ex2 is the correct format but you get there by accident, by allocating a new CompletableFuture and calling a static method, but in ex2 you do not discard the returned value while in ex1 you do. 而ex2是正确的格式,但是您偶然通过分配新的CompletableFuture并调用静态方法而到达那里,但是在ex2中,您不会丢弃返回的值,而在ex1中,您却这样做。

In you ex1 and ex2 you are effectively calling the same method, the code I provided above for ex1 is correct for both cases where you call static correctly using class name and not discarding the returned object. 在您的ex1和ex2中,您实际上是在调用相同的方法,上面为ex1提供的代码对于使用类名正确调用static而不丢弃返回的对象的两种情况都是正确的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 使用 Mockito 测试 CompletableFuture.supplyAsync - Testing CompletableFuture.supplyAsync with Mockito ForkJoinPool在CompletableFuture.supplyAsync()中的行为 - Behaviour of ForkJoinPool in CompletableFuture.supplyAsync() CompletableFuture.supplyAsync() 没有 Lambda - CompletableFuture.supplyAsync() without Lambda 获取CompletableFuture.supplyAsync的结果 - Getting the result of a CompletableFuture.supplyAsync ExecutorService.submit(Task)vs CompletableFuture.supplyAsync(Task,Executor) - ExecutorService.submit(Task) vs CompletableFuture.supplyAsync(Task, Executor) 简单的 CompletableFuture.supplyAsync() 导致 IllegalMonitorStateException 错误 - Simple CompletableFuture.supplyAsync() leads to IllegalMonitorStateException error 使用CompletableFuture.supplyAsync返回多个值 - Returning multiple values with CompletableFuture.supplyAsync CompletableFuture.supplyAsync 代码的代码覆盖率 - code coverage of CompletableFuture.supplyAsync code 如何将CompletableFuture.supplyAsync与PriorityBlockingQueue一起使用? - How do I use CompletableFuture.supplyAsync together with PriorityBlockingQueue? JDK8 CompletableFuture.supplyAsync 如何处理interruptedException - JDK8 CompletableFuture.supplyAsync how to deal with interruptedException
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM