【问题标题】:Timeout while waiting for a batch of Futures to complete?等待一批期货完成时超时?
【发布时间】:2013-06-30 08:03:14
【问题描述】:

我通过将Callables 提交给Executor 创建了一组Futures。伪代码:

for all tasks
  futures.add(executor.submit(new callable(task)))

现在我想让所有期货最多等待 n 秒,直到全部完成。我知道我可以打电话给Future#get(timeout),但是如果我在一个循环中为我所有的期货按顺序调用它,那么超时就会开始加起来。伪代码:

for all futures
  future.get(timeout)

get 在结果准备好之前超时阻塞。因此,如果第一个在超时之前完成,而第二个也在超时之前完成,以此类推,整个执行时间最多为number of futures * timeout 而不是timeout

因此,我正在寻找一种方法,它接受Futures 列表和超时,并行运行,然后返回未来结果的集合。有什么想法吗?

【问题讨论】:

  • 这还不完全清楚。您希望超时到期时尚未完成的任务发生什么?您希望它们被取消还是允许继续?
  • 他们应该被取消。此外,不知何故,我需要知道哪些已完成,哪些未完成。我想为此我可以再次迭代期货并在所有期货上调用isDone

标签: java concurrency future java.util.concurrent


【解决方案1】:

你可以使用ExecutorService.invokeAll:

执行给定的任务,当全部完成或超时到期(以先发生者为准)时,返回保存其状态和结果的 Futures 列表。 Future.isDone() 对于返回列表的每个元素都为真。返回时,未完成的任务将被取消。请注意,已完成的任务可能已经正常终止,也可能通过引发异常终止。如果在此操作进行时修改了给定的集合,则此方法的结果是不确定的。


如果您已经有需要监控的Futures 并且不能使用invokeAll,您可以简单地自己测量超时。伪代码:

long endTime = System.currentTimeMillis() + timeoutMS;
for(f : futures)
    f.get(Math.max(0, endTime - System.currentTimeMillis()), TimeUnit.MILLISECONDS);

这样,您最多可以为每个未来提供直到超时为止的持续时间。

【讨论】:

  • ExecutorService.invokeAll 听起来像我所追求的,谢谢。对于所有未及时完成的​​期货isCancelled==true,对吧(这就是我解释 Javadoc 的方式)?我如何知道 Future 是否完成异常? “请注意,已完成的任务可能会正常终止,也可能会通过引发异常而终止”——这很难……
  • @MarcelStör 是的,未完成的期货将被取消 (isCancelled() == true)。然后,当您将其称为 get()(在 invokeAll 返回之后)时,您可以确定 Future 发生了什么。如果get 抛出CancellationException,你就知道它已经被取消了。如果抛出ExecutionException,则表示Future发生异常,异常可通过ExecutionException.getCause()访问。
猜你喜欢
  • 2018-08-22
  • 2023-03-16
  • 2015-08-24
  • 1970-01-01
  • 1970-01-01
  • 2013-06-29
  • 1970-01-01
相关资源
最近更新 更多