下面是伪代码的片段。下面的代码不是打败了并行异步处理的概念吗?
我问这个问题的原因是因为在下面的代码中,主线程将提交一个任务在另一个线程中执行。在队列中提交任务后,它会阻塞Future.get()方法,以使任务返回值。我宁愿在主线程中执行任务,而不是提交到不同的线程并等待结果。我在新线程中执行任务获得了什么?
我知道你可以等待有限的时间等,但如果我真的关心结果呢?如果有多个任务要执行,问题会变得更糟。在我看来,我们只是在同步地做工作。我知道Guava库提供了一个非阻塞的侦听器接口。但我很想知道我对Future.get()API的理解是否正确。如果它是正确的,为什么Future.get()被设计成阻塞,从而破坏整个并行处理过程?
我使用Java 6。
public static void main(String[] args){
private ExectorService executorService = ...
Future future = executorService.submit(new Callable(){
public Object call() throws Exception {
System.out.println("Asynchronous Callable");
return "Callable Result";
}
});
System.out.println("future.get() = " + future.get());
}
5条答案
按热度按时间wfauudbj1#
Future
为您提供了方法isDone()
,该方法没有阻塞,如果计算完成,则返回true,否则返回false。Future.get()
用于检索计算结果。你有几个选择:
isDone()
,如果结果就绪,则通过调用get()
来请求它,请注意没有阻塞get()
无限期阻塞get(long timeout, TimeUnit unit)
阻止指定的超时整个
Future API
的存在是为了从执行并行任务的线程中获得值。如果您愿意,可以同步或异步完成,如上面的项目符号所述。使用缓存示例更新
下面是 Java Concurrency In Practice 中的一个缓存实现,这是
Future
的一个很好的用例。Future
中用于其他调用者。这一切都可以通过
Future
API轻松实现。vxf3dgd42#
下面是伪代码的片段。我的问题是--下面的代码是否违背了并行异步处理的概念?
这一切都取决于你的用例:
1.如果你真的想阻塞直到得到结果,使用阻塞
get()
1.如果您可以等待一段特定的时间来了解状态,而不是无限的阻塞持续时间,请使用带超时的
get()
1.如果您可以继续而不立即分析结果,并在将来检查结果,请使用CompletableFuture(java 8)。
可以显式完成(设置其值和状态)的Future,并且可以用作CompletionStage,支持在其完成时触发的依赖函数和动作。
1.您可以从Runnable/Callable实现回调机制。看看下面的问题:
Java executors: how to be notified, without blocking, when a task completes?
ktecyv1j3#
我想在这一点上给予我的观点,更多的是从理论的Angular 来看,因为已经有一些技术上的答案。我想根据以下评论来回答:
让我给你举个例子。我提交给服务的任务最终会引发HTTP请求,HTTP请求的结果可能需要很多时间。但是我需要每个HTTP请求的结果。任务在循环中提交。如果我等待每个任务返回(get),那么我就失去了并行性,不是吗?
这与问题中的内容一致。
假设你有三个孩子,你想为你的生日做一个蛋糕。因为你想做最好的蛋糕,你需要很多不同的东西来准备它。所以你要做的是把成分分成三份不同的清单,因为你住的地方只有三家超市出售不同的产品,然后给你的每个孩子分配一项任务,
simultaneously
。现在,在你开始准备蛋糕之前(让我们再次假设,你需要事先准备好所有的成分),你必须等待必须做最长路线的孩子。现在,在开始制作蛋糕之前需要等待所有成分的事实是你的必需品,而不是任务之间的依赖性。你的孩子已经尽可能长时间地同时完成了这些任务(例如:直到第一个孩子完成任务)。所以,总而言之,这就是平行论。
当你有一个孩子,你把所有三个任务都分配给他/她时,描述了顺序的例子。
pvabu6sv4#
在你给出的例子中,你可以运行你的
main()
方法中的所有东西,然后继续你的快乐之路。但是,让我们假设您有三个计算步骤,您当前正在顺序运行。为了便于理解,让我们假设步骤1需要t1秒,步骤2需要t2秒,步骤3需要t3秒完成。所以总计算时间是
t1+t2+t3
。假设t2>t1>=t3
。现在让我们考虑一个场景,当我们使用
Future
来保存每个计算结果时,我们并行执行这三个步骤。您可以检查每个任务是否在相应的future上使用非阻塞isDone()
调用完成。现在怎么办?理论上你的执行速度和t2
一样快,对吗?所以我们确实从并行性中获得了一些好处。另外,在Java8中,有
CompletableFuture
支持函数式回调。eyh26e7m5#
如果您不关心结果,那么生成一个新线程,并从该线程使用
ExectorService
API进行任务提交。这样,你的父线程,即main
线程,将不会以任何方式阻塞,它只会产生一个新线程,然后将开始进一步执行,而新线程将提交你的任务。对于创建新线程--要么自己做,用一个
ThreadFactory
来创建异步线程,要么使用java.util.concurrent.Executor
的一些实现。如果这是在JEE应用程序中,并且您正在使用Spring框架,那么您可以使用
@async
注解轻松创建新的异步线程。希望这有帮助!