首页 文章

关闭ExecutorService的两个实例

提问于
浏览
2

我需要在一种方法中正确关闭Executor Service的两个实例 .

这是我的简化代码:

ExecutorService executor1 = Executors.newSingleThreadExecutor();
ScheduledExecutorService executor2 = Executors.newSingleThreadScheduledExecutor();
// logic here
executor1.shutdown();
executor2.shutdown();
try {
    if (!executor1.awaitTermination(1, TimeUnit.SECONDS)) {
        executor1.shutdownNow();
    }
} catch (InterruptedException ex) {
    throw new IllegalStateException(ex);
}
try {
    if (!executor2.awaitTermination(1, TimeUnit.SECONDS)) {
        executor2.shutdownNow();
    }
} catch (InterruptedException ex) {
    throw new IllegalStateException(ex);
}

InterruptedException 被转换为 IllegalStateException ,因为我不希望这里有任何中断,这将意味着我的应用程序进入非法状态 .

我在这个解决方案中看到了一个缺陷 - 每当第一个执行者关闭时抛出异常,第二个 Actuator 将无法正常关闭 . 这里应该采用什么方法?如何安全地关闭 ExecutorService 的两个实例?

我宁愿避免嵌套 try-finally 块,因为我可能需要添加第三个 Actuator 服务,代码将变得无法管理 .

1 回答

  • 2

    至于类似的情况:

    Apache Commons IO有closeQuietly()关闭流(或者更确切地说是任何 Closeable ),而忽略关闭期间的任何异常 .

    public void shutdownQuietly(ExecutorService executor)
    {
        try {
            if (!executor.awaitTermination(1, TimeUnit.SECONDS)) {
                executor.shutdownNow();
            }
        } catch (InterruptedException ex) {
           /* IGNORE */
        }  
    }
    

    如果你需要这些例外,你可以尝试一些更邪恶的诡计:

    class MultiExecutorShutdown
    {
         private final List<InterrupedException> exceptions = new ArrayList<>();
    
         public void shutdown(ExecutorService service)
         {
             try {
                 if (!executor.awaitTermination(1, TimeUnit.SECONDS)) {
                    executor.shutdownNow();
                 }
             } catch (InterruptedException ex) {
                 exceptions.add(ex);
             }
         }
    
         public Optional<InterruptedException> getLastException()
         {
             if (exceptions.isEmpty()) {
                return Optional.empty();
             } else {
                 return exceptions.get(exceptions.size() - 1);
             }
         }
    
         public Optional<InterruptedException> getFirstException()
         {
             if (exceptions.isEmpty()) {
                return Optional.empty();
             } else {
                 return exceptions.get(0);
             }
         }
    }
    
    
    [...]
    MultiExecutorShutdown multiShutdown = new MultiExecutorShutdown();
    multiShutdown.shutdown(executor1);
    multiShutdown.shutdown(executor2);
    multiShutdown.shutdown(executor3);
    
    Optional<InterruptedException> exception = multiShutdown.getLastException();
    // alternative:
    // Optional<InterruptedException> exception = multiShutdown.getFirstException();
    
    if (exception.isPresent()) {
       throw new IllegalStateException(exception.get());
    }
    

    如果还需要失败的执行程序,还可以修改 MultiExecutorShutdown 以保留(有序)映射 ExecutorService -> Exception .

    你也可以把它扔进 MultiExecutorShutdown 本身,使它更有用 . 最后,整个事情可以 - 当然 - 被抽象出来,以便它需要一个功能,调用并记录抛出的任何异常 .

相关问题