Java 关闭ExecutorService的两个实例
我需要在一个方法中正确关闭两个Executor服务实例 以下是我的简化代码: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 {
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对的实现需要根据特定用例进行定制。如果需要所有三个异常,请添加适当的访问器方法。您甚至可以使用策略模式使解决方案可插拔,但这可能会过度设计解决方案。