繁体   English   中英

是什么导致ExecutorService.invokeAll()抛出InterruptedException?

[英]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:40‌​0)抛出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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM