【发布时间】:2016-01-29 17:15:24
【问题描述】:
我有一个可调用的列表,我想并行启动它们,给它们 5 秒的时间来完成,并使用在该时间内完成的任何任务的结果。
我尝试使用 executorService.invokeAll 超时,但在这种情况下,它们都需要在我超时之前完成。
使用 Java 7 执行此操作的最佳方法是什么?
【问题讨论】:
标签: java executorservice java.util.concurrent
我有一个可调用的列表,我想并行启动它们,给它们 5 秒的时间来完成,并使用在该时间内完成的任何任务的结果。
我尝试使用 executorService.invokeAll 超时,但在这种情况下,它们都需要在我超时之前完成。
使用 Java 7 执行此操作的最佳方法是什么?
【问题讨论】:
标签: java executorservice java.util.concurrent
我所做的是提交所有任务并将 Futures 添加到列表中。
然后您可以等待超时,并获取所有 isDone() 为 true 的 Future。
或者,您可以在每个 Futures 上调用 get,根据剩余时间量减少超时。
【讨论】:
只需在 5s 后检查 Future 是否使用 isDone 终止:
List<Callable<V>> callables = // ...
ExecutorService es = Executors.newFixedThreadPool(callables.size()));
List<Future<V>> futures = es.invokeAll(callables);
// Wait 5s
Thread.sleep(5000);
List<V> terminatedResults = new ArrayList<>();
for(Future<V> f : futures) {
if(f.isDone()) {
terminatedResults.add(f.get());
} else {
// cancel the future?
}
}
// use terminatedResults
【讨论】:
好的,这些答案帮助我找到了解决方案。 Logeart 的答案的问题是我想给他们一个最长的时间——所以如果他们完成得更快,我会全部搞定(抱歉,如果问题中不清楚)。
另一个问题是 isDone() 无法捕获任务被取消的情况 - 您需要使用 isCancelled()。所以,我的工作解决方案是:
ExecutorService exectutorService = Executors.newCachedThreadPool();
List<Callable<Object>> callables = Arrays.asList(
(Callable(Object) new Check1Callable(),
(Callable(Object) new Check2Callable(),
(Callable(Object) new Check3Callable());
List<Future<Object>> futures = new ArrayList<>();
try {
futures = executorService.invokeAll(callables,maxWaitTime, TimeUnit.SECONDS);
} catch (Exception e) {
}
for (Future thisFuture : futures) {
try {
if (thisFuture.isDone() && !thisFuture.isCancelled()) {
<accept the future's result>
}
} catch (Exception e) {
}
}
【讨论】: