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

未能在线程执行程序上调用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 … } 

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

那么:你如何自动关闭服务呢? 以一致的方式适用于每个人?!

所以,我眼中的合理解释是:你不能使ExecutorService成为AutoClosable,因为该服务没有单一的“关闭”操作; 但是两个!

如果您认为可以充分利用这种自动关闭服务,那么使用“委托”编写自己的实现将是一个5分钟的事情! 或者大概10分钟,因为你会创建一个版本调用shutdown()作为关闭操作; 和一个做shutdownNow()

这是一个平庸的解决方法

 ExecutorService service = Executors.newSingleThreadExecutor(); try (Closeable close = service::shutdown) { } 

当然,您必须永远不要在赋值和try语句之间放置任何东西,也不要在try语句之后使用service local变量。

考虑到警告, finally使用。

我没有看到AutoCloseable对Executor有用的地方。 try-with-resources用于可以在方法范围内初始化,使用和发布的内容。 这适用于文件,网络连接,jdbc资源等,可以快速打开,使用和清理。 但是执行程序,特别是线程池,是你想要长时间可用的东西,可能是在应用程序的整个生命周期中,并且往往会被注入像单例服务这样的东西,它可以有一个DI框架知道的方法。调用应用程序关闭来清理执行程序。 这种使用模式在没有资源尝试的情况下工作正常。

此外,尝试资源背后的一个重要动力是确保exception不被掩盖。 这对执行者来说不是一个考虑因素,所有exception抛出都将发生在提交给执行者的任务中,exception掩盖不是问题。

Try-with-resources是关于Readers / Streams的自动关闭,其中ExecutorService是关于使用线程池执行任务的。

所以我不确定两者之间是否存在并行关系,我们可以考虑将try-with-resources应用于ExecutorServices。

更新
引用Java语言规范:

try-with-resources语句使用变量(称为资源)进行参数化,这些变量在执行try块之前初始化并在执行try块后以与其初始化相反的顺序自动关闭。 当资源自动关闭时,通常不需要catch子句和finally子句。

规范将变量称为“资源” 。 所以我不确定ExecutorService是否可以作为资源调用,所以不要认为ExecutorService与Readers / Streams / Statement / ResultSet / Connection等并行。