我不明白CompletableFuture / supplyAsync在这里发生了什么。
如果我从先前实例化的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);
}
这是输出:
Start: cf = java.util.concurrent.CompletableFuture@5b480cf9[Not completed]
Main.m3
如您所见,
System.out.println("End: cf = " + cf);
从未执行。为了使其运行,我需要在supplyAsync主体中放置一个
complete(my value)
。但是,如果我在创建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);
}
它按预期工作。您可以在此处看到输出:
Start: cf = java.util.concurrent.CompletableFuture@5b480cf9[Not completed]
Main.m3
End: value = Main
所以我的问题是:为什么这样?我有什么想念的吗?
最佳答案
supplyAsync
是返回新static
的CompletableFuture
方法,不应通过实例调用它。
在第一种情况下,您正在从未启动任何内容的get()
上调用CompletableFuture
。
实际上,您会注意到,调用ex1()
时,程序将永远保持pending
状态。因此,它永远无法执行下一行,该行将打印(并行计算的其他Main
的)结果Future
。
关键是您不要在任何地方存储第二个CompletableFuture
。因此,您将无法调用正确的get()
。
在第二种情况下,您将使用返回值supplyAsync
构建实例,并将其存储在cf
中。这是构造CompletableFuture
的正确方法。 (new CompletableFuture<>()
部分是多余的;实际上,您可以通过supplyAsync
立即为其分配一个新实例)。
因此,当您调用get()
时,您将等待正确的CompletableFuture
返回其结果。
关于java - CompletableFuture.supplyAsync与新的CompletableFuture(),我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/48906538/