2013-07-02 68 views
6

我通过将Callable s提交到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

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

+0

这并不完全清楚。当超时到期时,你想要发生什么还没有完成的任务?你希望他们被取消还是被允许继续? –

+0

他们应该被取消。另外,不知何故,我需要知道哪些已完成,哪些没有完成。我想因为我可以在期货上重复一遍,并在所有期货上调用'isDone'。 –

回答

5

您可以使用ExecutorService.invokeAll

执行给定的任务,返回保持状态期货和结果的列表时,所有任务完成或超时期满时,先发生者为准。 Future.isDone()对于返回列表的每个元素都是true。返回后,尚未完成的任务将被取消。请注意,完成的任务可能正常结束或通过抛出异常终止。如果在进行此操作时修改了给定集合,则此方法的结果未定义。


如果你已经有Future是你们等需要监控和不能使用invokeAll,你可以简单地衡量自己的超时。伪代码:

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

这样,您最多可以给出每个未来的持续时间,直到您到达超时。

+0

'ExecutorService.invokeAll'听起来像我之后,谢谢。对于所有未及时完成的​​期货'isCancelled == true',对(我如何解释Javadoc)?我将如何查明“Future”是否完成,但有异常? “请注意,完成的任务可能正常结束或通过抛出异常终止” - 这很难... –

+1

@MarcelStör是的,未完成的期货将被取消('isCancelled()== true')。然后,当您将其称为['get()']时,您可以确定'Future'发生了什么事情(http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/Future.html#得到%28%29)(在'invokeAll'返回之后)。如果'get'抛出'CancellationException',你知道它已被取消。如果它引发'ExecutionException',则意味着未来完成了一个异常,并且可以通过'ExecutionException.getCause()'来访问异常。 –