如何在退出应用程序时关闭所有Executor?

Joo*_*kka 10 java concurrency

根据Brian Goetz的Java Concurrency in Practice,JVM无法退出,直到所有(非守护程序)线程都终止,因此无法关闭Executor可能会阻止JVM退出.

即如果存在执行程序,System.exit(0)不一定按预期工作.似乎有必要放一些

public void stop() { exec.shutdown() }
Run Code Online (Sandbox Code Playgroud)

包含Executors的所有类的方法,然后在应用程序即将终止时调用它们.这是唯一的方法,还是有某种关闭所有Executors的快捷方式?

ska*_*man 14

没有捷径可以做到这一切,没有.此外,你应该打电话shutdownNow()而不是shutdown(),否则你可能会等待一段时间.

我想你可以做的是,当你创建Executor时,将它注册在一个中心位置.然后,当关闭时,只需调用shutdown()该中心对象,这反过来可以终止每个注册的执行程序.

如果您使用Spring,那么您可以利用其工厂bean为您创建和管理Executors.这包括在应用程序退出时正常关闭它们,并节省您必须自己管理它们.


Adr*_*iuk 9

使用com.google.common.util.concurrent.MoreExecutors#getExitingExecutorService装饰执行程序

@Beta
public static ExecutorService getExitingExecutorService(ThreadPoolExecutor executor,
                                         long terminationTimeout,
                                         TimeUnit timeUnit)
Run Code Online (Sandbox Code Playgroud)

将给定的ThreadPoolExecutor转换为在应用程序完成时退出的ExecutorService.它通过使用守护程序线程并添加一个关闭钩子来等待它们完成来实现.

这主要用于固定线程池.请参见Executors.newFixedThreadPool(int).


小智 8

默认情况下,Executor只会创建非守护程序线程.您可以通过向Executor提供自己的ThreadFactory来覆盖它.这是一个例子:

class DaemonThreadFactory implements ThreadFactory {
  public Thread newThread(Runnable r) {
    Thread t = new Thread(r);
    t.setDaemon(true);
    return t;
  }
}
Run Code Online (Sandbox Code Playgroud)

要谨慎,但是,因为JVM将退出的时候了,即使这些线程都在忙着做无用功!


shu*_*ckc 5

您还可以提供ThreadFactory的实现,该实现将创建的线程标记为守护线程.我更喜欢干净的关闭机制(使用生命周期方法),但有些情况下,如果合适,您不需要保证未完成任务的状态/完成.