无法在线程执行程序上调用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
…
}
答案 0 :(得分:17)
ExecutorService实际上有两个与关机相关的方法;基于一个简单的事实,两种关闭服务的方式都有意义。
因此:您如何自动关闭服务呢?以一致的方式适用于每个人?!
所以,我眼中的合理解释是:你不能使ExecutorService成为AutoClosable,因为该服务没有单一的“关闭”操作;但是两个!
如果您认为可以充分利用这种自动关闭服务,那么使用“委托”编写自己的实现将是一个5分钟的事情!或者大概10分钟,因为您将创建一个版本,调用shutdown()
作为关闭操作;而是改为shutdownNow()
的。
答案 1 :(得分:12)
这是一个平庸的解决方法
ExecutorService service = Executors.newSingleThreadExecutor();
try (Closeable close = service::shutdown) {
}
当然,您绝不能在赋值和try
语句之间放置任何内容,也不能在service
语句后使用try
局部变量。
考虑到警告,请改用finally
。
答案 2 :(得分:0)
我没有看到AutoCloseable对Executor有用的地方。 try-with-resources用于可以在方法范围内初始化,使用和发布的内容。这适用于文件,网络连接,jdbc资源等,可以快速打开,使用和清理。但是执行程序,特别是线程池,是你想要长时间使用的东西,可能是在应用程序的生命周期内,并且往往会被注入像单例服务那样的东西,这可以有一个DI框架知道的方法。调用应用程序关闭来清理执行程序。这种使用模式在没有资源尝试的情况下工作正常。
此外,尝试资源背后的一个重要动力是确保异常不被掩盖。对执行者来说,这不是一个考虑因素,所有异常抛出都将发生在提交给执行者的任务中, 异常屏蔽不是问题。
答案 3 :(得分:-1)
Try-with-resources是关于Readers / Streams的自动关闭,其中ExecutorService是关于使用线程池执行任务的。
所以我不确定两者之间是否存在并行关系,我们可以考虑将try-with-resources应用于ExecutorServices。
更新
引用Java语言规范:
try-with-resources语句使用变量(称为资源)进行参数化,这些变量在执行try块之前初始化并在执行try块后以与它们初始化的相反顺序自动关闭。当资源自动关闭时,通常不需要catch子句和finally子句。
规范将变量称为“resources”。所以我不确定是否可以将ExecutorService作为资源调用,因此不要将ExecutorService视为与读者/流/语句/结果集/连接等并行。