假设您有以下两种方法返回以下CompletableFutures
:
public CompletableFuture<String> initializeFirstCf(){
return new CompletableFuture<>();
}
public CompletableFuture<String> initializeSecondCf(){
CompletableFuture<String> b = new CompletableFuture<>();
b.thenApplyAsync(result -> {
// invoke an event RIGHT after "b" is completed. For example, printing "hello"
System.out.print("Hello from SECOND!");
return result;
});
return b;
}
现在让我们想象一下,我们有两个单独的线程同时调用以下两个方法。我们在.get()
调用中被阻止,直到将来完成为止(在单独的线程/进程中)。
public String getFirstCompletedValue(){
String result = initializeFirstCf().get(15000, TimeUnit.MILLISECONDS);
print("Hello from FIRST!")
return
}
public String getSecondCompletedValue(){
return initializeSecondCf().get(15000, TimeUnit.MILLISECONDS);
}
现在假设这两个期货同时完成。第一个Future不会通过thenApplyAsync()
应用另一个CompletionStage(就像第二个Future一样),但是在{{1}中得到结果后,我仍然立即调用相同的完成事件(在我们的情况下为print语句) }}。我的问题是,如果同时调用并完成这两种方法(getFirstCompletedValue()
和getFirstCompletedValue()
,那么在这种特定情况下,我是否有理由要提供{{ 1}}到CF的功能,如果我可以继续并在得到结果后做我想做的相同的事情?我可以通过getSecondCompletedValue()
路线使事情更快地成像,但是我想看看是否真的有必要。希望我的问题很清楚,谢谢您的提前帮助。
答案 0 :(得分:0)
您的getFirstCompletedValue()
和getSecondCompletedValue()
在实现的功能上可能是等效的,但是对于initializeFirstCf()
和initializeSecondCf()
来说却不能这么说。
何时使用thenApply
取决于第二个链式执行的调用位置。这意味着这取决于您认为进行System.out.print("Hello from SECOND!");
通话的合适位置。
当您设计返回Future
的API方法时,您就会知道未来的含义。如果这还不能完全代表get()
到期时呼叫者想要运行的内容,那么他们可以在以后添加thenApply
。
在返回未来方法的文档中,API开发人员明确指出println
在get()
将返回所生成的未来时运行还是未运行。如果它没有运行,并且呼叫者希望呼叫print
,则他们需要呼叫thenApply
,thenAccept
,就像在getFirstCompletedValue
中一样。
这是关于未来代表什么的问题。 cf1.thenApply(function)
是代表cf1
完成的任务,接着是任务function
完成的未来。但是完成的cf1
代表已完成的任务。因此,从概念上讲,如果某个方法返回任务cf1
的值,则调用者会知道function
没有运行,并且可能在收到的将来完成后需要调用。