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

Adr*_*ebs 25 java multithreading interface try-with-resources

未能调用shutdown()线程执行程序将导致永不终止的应用程序.关闭ExecutorService的最佳做法是:

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

由于Java知道try-with-resources概念,如果我们能做到这一点会不会很好?

try (service = Executors.newSingleThreadExecutor())
{
  // add tasks to thread executor
  …
} 
Run Code Online (Sandbox Code Playgroud)

Gho*_*ica 19

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

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

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

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


wil*_*mol 19

ExecutorService使用AutoCloseableJava 19+

从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();
      }
    }
  }
}
Run Code Online (Sandbox Code Playgroud)


Luk*_*der 15

这是一个平庸的解决方法

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

}
Run Code Online (Sandbox Code Playgroud)

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

考虑到警告,请finally改用.