好的,所以我知道这里的第一个答案/评论是“使用一个ExecutorService
并使用invokeAll
”。但是,有一个很好的理由(我不会让人厌烦)让我们保持线程池分开。
所以我有一个线程池列表(ExecutorServices
),我需要做的是使用Callable
在每个线程池上调用不同的submit
(没问题)。现在我有了Future
个实例的集合,每个实例都是在一个单独的ExecutorService
上创建的,我想等待所有这些实例完成(并且能够提供超时完成取消)。
是否有现有的类可以执行此操作(包装Future
实例列表并允许等待直到完成所有操作)?如果没有,将赞赏有效机制的建议。
考虑为每个调用get
调用超时,但必须计算每次调用的总时间。
我看到了这篇文章Wait Until Any of Future is Done,但这扩展了Future
而不是包含它们的列表。
答案 0 :(得分:17)
答案 1 :(得分:2)
我不认为JDK提供了一个直接的API,可以让你这样做。但是,我认为创建一个执行此操作的简单方法同样简单。您可能需要查看AbstractExecutorService.invokeAll()的实现,以了解可以这样做。
基本上,你会在每个未来调用future.get(),每次等待结果所花费的时间减少等待时间,并且在从方法返回之前取消所有未完成的期货。
答案 2 :(得分:1)
也许我没有真正理解它。然而,对我来说,它仍然听起来像
一样简单public <V> List<V> get(List<Future<V>> futures, long timeout, TimeUnit unit)
throws InterruptedException, ExecutionException, TimeoutException {
List<V> result = new ArrayList<V>();
long end = System.nanoTime() + unit.toNanos(timeout);
for (Future<V> f: futures) {
result.add(f.get(end - System.nanoTime(), TimeUnit.NANOSECONDS));
}
return result;
}
我错了吗?
我认为你链接的问题要复杂得多,因为他们只想等待最快,当然也不知道哪一个是最快的。
答案 3 :(得分:1)
这可以使用一些清理,但它应该可以解决您的问题。 (对时间和空间省略了一些封装):
public static <T> LatchWithWrappedCallables<T> wrapCallables(Collection<Callable<T>> callablesToWrap)
{
CountDownLatch latch = new CountDownLatch(callablesToWrap.size());
List<Callable<T>> wrapped = new ArrayList<Callable<T>>(callablesToWrap.size());
for (Callable<T> currCallable : callablesToWrap)
{
wrapped.add(new CallableCountdownWrapper<T>(currCallable, latch));
}
LatchWithWrappedCallables<T> returnVal = new LatchWithWrappedCallables<T>();
returnVal.latch = latch;
returnVal.wrappedCallables = wrapped;
return returnVal;
}
public static class LatchWithWrappedCallables<T>
{
public CountDownLatch latch;
public Collection<Callable<T>> wrappedCallables;
}
public static class CallableCountdownWrapper<T> implements Callable<T>
{
private final Callable<T> wrapped;
private final CountDownLatch latch;
public CallableCountdownWrapper(Callable<T> wrapped, CountDownLatch latch)
{
this.wrapped = wrapped;
this.latch = latch;
}
@Override
public T call() throws Exception
{
try
{
return wrapped.call();
}
finally
{
latch.countDown();
}
}
}
然后你的代码会这样称呼它:
Collection<Callable<String>> callablesToWrap = [Your callables that you need to wait for here];
LatchWithWrappedCallables<String> latchAndCallables = wrapCallables(callablesToWrap);
[Submit the wrapped callables to the executors here]
if(latchAndCallables.latch.await(timeToWaitInSec, TimeUnit.SECONDS))
{
[Handling for timeout here]
}