根据Brian Goetz的Java Concurrency in Practice JVM在所有(非守护程序)线程终止之前无法退出,因此无法关闭Executor可能会阻止JVM退出。
即。如果有执行程序,System.exit(0)不一定按预期工作。似乎有必要提出某种
public void stop() { exec.shutdown() }
包含Executors的所有类的方法,然后在应用程序即将终止时调用它们。这是唯一的方法,还是有某种关闭所有执行程序的快捷方式?
答案 0 :(得分:14)
没有捷径可以做到这一切,没有。此外,您应该拨打shutdownNow()
而不是shutdown()
,否则您可能会等待一段时间。
我想你可以做的是,当你创建Executor时,将它注册在一个中心位置。然后,当关闭时,只需在该中心对象上调用shutdown()
,然后可以终止每个已注册的执行者。
如果您使用Spring,那么您可以利用其工厂bean为您创建和管理Executors。这包括在应用程序退出时优雅地关闭它们,并节省您自己管理它们的时间。
答案 1 :(得分:9)
使用com.google.common.util.concurrent.MoreExecutors#getExitingExecutorService
装饰执行程序@Beta
public static ExecutorService getExitingExecutorService(ThreadPoolExecutor executor,
long terminationTimeout,
TimeUnit timeUnit)
将给定的ThreadPoolExecutor转换为在应用程序完成时退出的ExecutorService。它通过使用守护程序线程并添加一个关闭钩子来等待它们完成来实现。
这主要用于固定线程池。请参阅Executors.newFixedThreadPool(int)。
答案 2 :(得分:8)
默认情况下,Executor只会创建非守护程序线程。您可以通过向Executor提供自己的ThreadFactory来覆盖它。这是一个例子:
class DaemonThreadFactory implements ThreadFactory {
public Thread newThread(Runnable r) {
Thread t = new Thread(r);
t.setDaemon(true);
return t;
}
}
但是要小心,因为即使这些线程忙于做有用的工作,JVM也会立即退出 !
答案 3 :(得分:5)
您还可以提供ThreadFactory的实现,该实现将创建的线程标记为守护程序线程。我更喜欢干净的关闭机制(使用生命周期方法),但有些情况下,如果合适,您不需要保证未完成任务的状态/完成。
答案 4 :(得分:0)
可能他的意思是说在非守护程序线程完成之前,JVM无法自行停止。它就像从Java SomeClass这样的命令运行一个简单的类,并且在主方法JVM的执行停止之后。
System.exit是一个JVM终止命令,即使守护程序线程正在运行,JVM也会关闭。