Java ExecutorService.invokeAll并关闭
因此,我有一些可调用的任务,对中断敏感,我使用invokeAll将其提交给ExecutorService。从另一个方法调用executorService.shutdownNow 5秒钟后,我调用WaitTermination,它返回true,因此一切看起来都很好。问题是执行人永远不会终止 由于日志记录,我知道我的每项任务都已完成。 然而,当i等于执行器的线程数时,invokeAll仍会阻塞f.get: 以下代码来自AbstractExecutorService+一些日志记录Java ExecutorService.invokeAll并关闭,java,concurrency,executor,Java,Concurrency,Executor,因此,我有一些可调用的任务,对中断敏感,我使用invokeAll将其提交给ExecutorService。从另一个方法调用executorService.shutdownNow 5秒钟后,我调用WaitTermination,它返回true,因此一切看起来都很好。问题是执行人永远不会终止 由于日志记录,我知道我的每项任务都已完成。 然而,当i等于执行器的线程数时,invokeAll仍会阻塞f.get: 以下代码来自AbstractExecutorService+一些日志记录 @O
@Override
public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks) throws InterruptedException {
if (tasks == null) throw new NullPointerException();
ArrayList<Future<T>> futures = new ArrayList<Future<T>>(tasks.size());
boolean done = false;
try {
List<Callable<T>> list = new ArrayList<Callable<T>>();
for (Callable<T> t : tasks) {
list.add(t);
RunnableFuture<T> f = newTaskFor(t);
futures.add(f);
execute(f);
}
for (int i = 0, size = futures.size(); i < size; i++) {
Future<T> f = futures.get(i);
if (!f.isDone()) {
log.info("Future %s is not done!. Task %s", i, list.get(i));
try {
log.info("Get from future %s", i);
// NEXT LINE BLOCKS FOR i= NUMBER OF THREADS
f.get();
log.info("Got result from future %s", i);
} catch (CancellationException ignore) {
} catch (ExecutionException ignore) {
}
}
}
log.info("Obtained all!");
done = true;
return futures;
} finally {
if (!done) for (int i = 0, size = futures.size(); i < size; i++)
futures.get(i).cancel(true);
}
}
@覆盖
public List invokeAll(Collection是的,您不应该在关机时使用invokeAll。至少这是我的理解,如果我错了,请纠正我
- Shutdownow方法:
公共列表关闭现在(){
...
checkShutdownAccess();
提前停止(停止);
打断工人();
tasks=drainQueue();
...
}
唯一要做的就是中断工作线程并从工作队列中删除其余的可运行程序,请参见drainQueue。ShutdownNow/Shutdown不会修改我们invokeAll方法中的未来
因此,在我的例子中,对于一个有N个线程的执行器,我调用了300个作业,每个作业都需要1分钟以上的时间,5秒钟后我取消(中断工作线程),N个线程被中断(0到N-1)。剩下的将来会发生什么?无,下一次调用f.get()(参见问题中的对应行)将阻塞,而您将被困在那里。这解释了为什么我总是在I=线程数时被阻塞
public List<Runnable> shutdownNow() {
...
checkShutdownAccess();
advanceRunState(STOP);
interruptWorkers();
tasks = drainQueue();
...
}