在实用程序库中,我正在创建一个 ExecutorService
ExecutorService es = Executors.newSingleThreadExecutor();
主线程随后会将一些任务发布到这个ExecutorService。当主线程完成时,我想关闭 ExecutorService 以允许应用程序退出。
问题是我只能更改实用程序库中的代码。我考虑的一种选择是使用守护线程。但随后它会在发布到服务的任务完成之前突然关闭。
Runtime#addShutdownHook()
将关闭钩子添加到当前运行时。
例如
Runtime.getRuntime().addShutdownHook(new Thread() {
public void run() {
es.shutdown();
try {
es.awaitTermination(5, TimeUnit.SECONDS);
} catch (InterruptedException e) {
logger.info("during await",e);
}
}
});
在构建/初始化实用程序类时执行此操作。
shutdownHook
将不起作用。原因在这里
shutdownhook
当 JVM 开始退出时启动,除非你调用 es.shutDown()
,否则 JVM 不会退出,所以它是一个死锁。
我不知道为什么制作守护进程执行器不起作用。它应该。守护进程执行器在主类启动的所有线程完成执行之前不会关闭(除非它们也是守护进程)
创建执行器时尝试此代码
ExecutorService es = Executors.newSingleThreadExecutor( new ThreadFactory() {
@Override
public Thread newThread(Runnable r) {
Thread t = new Thread(r);
t.setDaemon(true);
return t;
}
});
final ExecutorService executor;
Runtime.getRuntime().addShutdownHook(new Thread() {
public void run() {
executor.shutdown();
try {
if (!executor.awaitTermination(SHUTDOWN_TIME, TimeUnit.SECONDS)) {
// Optional: Log that the executor still had tasks to process after waiting the specified time.
Logger.log("Executor did not terminate within the specified time.");
// Optional: Attempt to forcefully terminate the executor's worker threads.
List<Runnable> droppedTasks = executor.shutdownNow();
Logger.log("Executor was abruptly shut down. " + droppedTasks.size() + " tasks will not be executed.");
}
} catch (InterruptedException e) {
// Handle interruption while waiting for termination (if needed).
}
}
});
注:
此外,值得注意的是,当处理 Java 进程的中断或 ExecutorService 仅由守护线程组成时,此解决方案非常有效。如果非守护线程存在且尚未完成,JVM 可能不会尝试关闭,因此不会调用关闭挂钩。在这种情况下,如果关闭是离散应用程序生命周期的一部分,则关闭代码应放置在程序设计终止的适当位置,而不是放置在关闭挂钩内。