[英]What can cause ExecutorService.invokeAll() to throw an InterruptedException?
javadoc说invokeAll(Collection<> callables)
抛出
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调用彼此混淆吗?)
是什么导致
ExecutorService.invokeAll()
抛出InterruptedException
?
参见javadoc中的shutdownNow()
:
除了尽最大努力尝试停止处理正在执行的任务之外,没有任何保证。 例如,典型的实现将通过
Thread.interrupt()
取消,因此任何无法响应中断的任务都可能永远不会终止。
由于invokeAll
等待直到完成所有任务,因此从另一个线程调用shutdownNow()
是可以中断invokeAll
调用的一种方式。
但是,在您向我们展示的代码中 ,没有对shutdownNow()
调用,也没有明显的方式使执行程序服务对象泄漏到另一个线程。
您的代码(或某些其他库代码)中的某些内容也可能正在调用Thread.interrupt
。 例如,一项任务可能就是自己执行此操作。
这些ParallelUtils可以同时运行很多(从不同的线程启动)
显然,这些线程中的至少一个直接通过Thread.interrupt()
中断,或通过例如Future.cancel(true)
或ExecutorService.shutdownNow()
间接中断。
重现此中断的示例:
class Sleep implements ParallelUtil.Task<Integer> {
@Override
public void execute(Integer data) throws Exception {
Thread.sleep(Long.MAX_VALUE);
}
}
class InterruptInvokeAll {
public static void main(String[] args) {
ExecutorService executorService = Executors.newFixedThreadPool(1);
executorService.submit(
() -> {
ParallelUtil<Integer> parallelUtil = new ParallelUtil<>();
parallelUtil.execute(new Sleep(), Arrays.asList(1));
});
executorService.shutdownNow(); // indirectly interrupts thread that calls executor.invokeAll
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.