java - 关闭两个 ExecutorService 实例

标签 java multithreading executorservice shutdown

我需要用一种方法正确关闭两个 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,因为我不希望这里有任何中断,这意味着我的应用程序进入了非法状态。

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

我宁愿避免嵌套的 try-finally block ,因为我可能需要添加第三个执行程序服务并且代码会变得难以管理。

最佳答案

至于类似的情况:

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

您还可以将 throw 插入 MultiExecutorShutdown 本身,使其更有用。最后,当然可以将整个事情抽象化,以便它接受一个函数,调用它并记录抛出的任何异常。

关于java - 关闭两个 ExecutorService 实例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34499389/

相关文章:

java - 解析 whereEqualTo

java - java中什么情况下try catch会被绕过?

java - 将 ArrayList 中的元素添加到一起

java线程和同步

scala - 没有用于 future 的守护线程的执行上下文

java - 提高逐行读取文件和处理的性能

java - 在当前主题中找不到样式 'navigationViewStyle'

c++ - 条件变量和#pragma pack bug

java - fork /加入 : Collecting results

Java 执行器和长生命周期线程