【发布时间】:2017-08-30 09:37:50
【问题描述】:
javadoc 说 invokeAll(Collection<> callables) throws
InterruptedException - 如果在等待时被中断,则取消未完成的任务
但没有关于为什么呼叫会被中断的文档。我的程序会这样做——但很少发生,我无法编写会导致它发生的测试。
我正在使用没有超时的单参数方法。
public class ParallelUtil<T> {
public interface Task<T> {
public void execute(T data) throws Exception;
}
public void execute(final Task<T> task, Collection<T> targets) {
ExecutorService executor = null;
try {
executor = Executors.newFixedThreadPool(20);
execute(task, targets, executor);
} finally {
if (executor != null) {
try {
executor.shutdown();
} catch (Exception e) {}
}
}
}
private void execute(final Task<T> task, Collection<T> targets, ExecutorService executor) {
List<Callable<Void>> tasks = new ArrayList<>();
...
try {
executor.invokeAll(tasks);
} catch (Exception e) {
// Here we get InterruptedException - for no reason?
// With some of the tasks left undone!
}
}
}
从java.util.concurrent.FutureTask.awaitDone(FutureTask.java:400) 抛出(至少在某些情况下)InterruptedException
可以同时运行许多ParallelUtils(从不同的线程启动),但正如您所见,每个调用都会创建自己的ExecutorService,因此它们不应相互混淆。
(作为一个附带问题,我可以为所有调用使用共享池,而不会使 invokeAll 调用相互混淆吗?)
【问题讨论】:
-
} catch (Exception e) {}你不会真的吞下去吧? -
我会用一个工具来装饰任务,以捕获 InterruptedExceptions 以找出哪些是被中断的。我怀疑中断发生在一个(或多个)任务的执行代码中。
-
@Fildor 不,我不会吞下它们,我会用一些调试数据在那里抛出另一个异常。我不完全确定装饰器应该是什么样子——中断发生在 invokeAll() 的内部逻辑中(更准确地说是在 java.util.concurrent.FutureTask.awaitDone(FutureTask.java:400) 中——我应该添加这个位问题的信息)
-
回到这个问题,原因如下:我的线程是由线程中运行的东西创建的。创建线程被中断(我知道会发生这种情况)-> 中断创建线程导致被中断线程创建的线程中断(没有完成它们的工作)。修复:创建线程的创建者中的一个标志,确保正在运行的线程不会被中断。
标签: java concurrency executorservice