为什么ExecutorService接口没有实现AutoCloseable?

问题描述 投票:0回答:5

未能在线程执行器上调用

shutdown()
将导致应用程序永远不会终止。

关闭 ExecutorService 的最佳实践是这样的:

ExecutorService service = null;
try {
  service = Executors.newSingleThreadExecutor();
  // add tasks to thread executor
  …
} finally {
  if (service != null) service.shutdown();
}

既然 Java 知道 try-with-resources 概念,如果我们能做到这一点不是很好吗?

try (service = Executors.newSingleThreadExecutor())
{
  // add tasks to thread executor
  …
} 
java multithreading interface try-with-resources
5个回答
32
投票

ExecutorService实际上有两个与关闭相关的方法;基于一个简单的事实:两种关闭服务的方法都是有意义的。

因此:那么你将如何自动关闭服务呢?以一致的方式对每个人都有效?!

所以,在我看来合理的解释是:你不能将 ExecutorService 设置为 AutoClosable,因为该服务没有单一的“关闭”之类的操作;但是两个!

如果你认为你可以很好地利用这样一个自动关闭服务,那么使用“委托”编写你自己的实现将是一个 5 分钟的事情!或者可能是 10 分钟,因为您将创建一个调用

shutdown()

 作为关闭操作的版本;以及一个做 
shutdownNow()
 的人。


29
投票
这是一个平庸的解决方法

ExecutorService service = Executors.newSingleThreadExecutor(); try (Closeable close = service::shutdown) { }
或者,如果受检查的异常困扰您,您可以写:

interface MyCloseable extends AutoCloseable { void close(); }
然后

ExecutorService service = Executors.newSingleThreadExecutor(); try (MyCloseable close = service::shutdown) { }
当然,您绝不能在赋值和 

try

 语句之间放置任何内容,也不能在 
service
 语句之后使用 
try
 局部变量。

鉴于注意事项,只需使用

finally

 即可。


25
投票

ExecutorService
 在 Java 19+ 中是 
AutoCloseable

Java 19 开始,ExecutorService

 实现了 
AutoCloseable

默认实现调用

shutdown()

 并在循环中使用 
awaitTermination
 等待任务完成。如果被中断,它会调用 
shutdownNow()

谷歌番石榴

对于早期的Java,你可以使用

Guava的ForwardingExecutorService

来自己装饰ExeuctorService
AutoCloseable

class CloseableExecutorService extends ForwardingExecutorService implements AutoCloseable { private final ExecutorService delegate; CloseableExecutorService(ExecutorService delegate) { this.delegate = checkNotNull(delegate); } @Override protected ExecutorService delegate() { return delegate; } @Override public void close() { // copy paste from JDK 19 EA boolean terminated = isTerminated(); if (!terminated) { shutdown(); boolean interrupted = false; while (!terminated) { try { terminated = awaitTermination(1L, TimeUnit.DAYS); } catch (InterruptedException e) { if (!interrupted) { shutdownNow(); interrupted = true; } } } if (interrupted) { Thread.currentThread().interrupt(); } } } }
    

2
投票
我不明白 AutoCloseable 对 Executor 有何用处。 try-with-resources 适用于可以在方法范围内初始化、使用和释放的事物。这对于文件、网络连接、jdbc 资源等非常有用,它们可以快速打开、使用和清理。但是执行器,尤其是线程池,是您希望在很长一段时间内(可能在应用程序的整个生命周期内)可用的东西,并且往往会被注入到诸如单例服务之类的东西中,这些服务可以具有 DI 框架知道的方法调用应用程序关闭来清理执行器。这种使用模式无需尝试资源即可正常工作。

此外,try-with-resources 背后的一个重要动机是确保异常不会被掩盖。对于执行器来说,这不是一个需要考虑的问题,所有异常抛出都将发生在提交给执行器的任务中, 异常屏蔽不是问题。


0
投票
JAVA 示例 - ExecutorService 从 Java 19+ 开始可自动关闭

如官方文档中所述 -

here

实现此功能的 Java 示例 -

try(ExecutorService executorService = Executors.newFixedThreadPool(10)){ //do stuff with you executor service executorService.shutdown(); try { if (!executorService.awaitTermination(60, TimeUnit.SECONDS)) { log.warn("Shutting Down Executor forcefully .... "); executorService.shutdownNow(); } }catch (InterruptedException e) { executorService.shutdownNow(); Thread.currentThread().interrupt(); } finally { log.info("----------FINISHED PROCESSING--------------"); } }
    
最新问题
© www.soinside.com 2019 - 2025. All rights reserved.