Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/348.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 关闭ExecutorService的两个实例_Java_Multithreading_Executorservice_Shutdown - Fatal编程技术网

Java 关闭ExecutorService的两个实例

Java 关闭ExecutorService的两个实例,java,multithreading,executorservice,shutdown,Java,Multithreading,Executorservice,Shutdown,我需要在一个方法中正确关闭两个Executor服务实例 以下是我的简化代码: ExecutorService executor1 = Executors.newSingleThreadExecutor(); ScheduledExecutorService executor2 = Executors.newSingleThreadScheduledExecutor(); // logic here executor1.shutdown(); executor2.shutdown(); try {

我需要在一个方法中正确关闭两个Executor服务实例

以下是我的简化代码:

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
,因为我不希望这里有任何中断,这意味着我的应用程序进入非法状态

我发现这个解决方案有一个缺陷——每当第一个执行器在关闭时抛出异常时,第二个执行器将无法正确关闭。正确的方法应该是什么?如何安全关闭执行器服务的两个实例


我希望避免嵌套的
try finally
块,因为我可能需要添加第三个执行器服务,代码将变得不可管理。

对于类似的情况:

Apache Commons IO有一个关闭流(或者更确切地说是任何可关闭的
),同时忽略关闭过程中的任何异常

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());
}
类多执行器关闭
{
私有最终列表例外=新ArrayList();
公共无效关闭(执行器服务)
{
试一试{
如果(!执行器等待终止(1,时间单位秒)){
执行者。关机现在();
}
}捕获(中断异常例外){
例外情况。添加(ex);
}
}
公共可选getLastException()
{
if(exceptions.isEmpty()){
返回可选的.empty();
}否则{
返回exceptions.get(exceptions.size()-1);
}
}
公共可选getFirstException()
{
if(exceptions.isEmpty()){
返回可选的.empty();
}否则{
返回异常。get(0);
}
}
}
[...]
MultiExecutorShutdown multiShutdown=新的MultiExecutorShutdown();
多停机。停机(执行器1);
多重停机。停机(执行器2);
多重停机。停机(执行器3);
可选异常=multiShutdown.getLastException();
//备选方案:
//可选异常=multiShutdown.getFirstException();
if(exception.isPresent()){
抛出新的IllegalStateException(exception.get());
}
如果您还需要失败的执行器,还可以修改
MultiExecutorShutdown
以保留(有序)映射
ExecutorService->Exception


您还可以将抛出推入
MultiExecutorShutdown
本身,使其更加可用。最后,整个过程可以——当然——被抽象,这样它就可以接受一个函数,调用它并记录抛出的任何异常。

这和:?@YacoZaragoza不是真的-这里我的代码示例被简化了,但我需要两个单独的执行器服务,一个是正常的,而第二个是计划执行器服务。明白了。。让我运行一些测试:-)当两个关机都引发异常时,您希望保留哪一个?如果你想两者都保留,您需要一个包装异常来包含它们。如果第一个出现故障,则安全信息,然后处理第二个,然后在根据先前的安全信息处理最后一个执行器之后抛出异常。如果三个
ExecutorServices
中的每一个抛出异常,则您将无法仅使用第一个和最后一个访问器方法访问它们。@harpun对的实现需要根据特定用例进行定制。如果需要所有三个异常,请添加适当的访问器方法。您甚至可以使用策略模式使解决方案可插拔,但这可能会过度设计解决方案。