JVM 如何终止守护进程线程?或如何编写正常终止的守护程序线程
2022-09-01 10:00:18
假设场景:
我有一个守护进程线程负责一些 I/O,主线程完成并返回,JVM 决定终止我的守护进程线程。
它是如何做到的?中断?完成?如何对守护进程线程进行编码,使其在终止时能够正常响应?
假设场景:
我有一个守护进程线程负责一些 I/O,主线程完成并返回,JVM 决定终止我的守护进程线程。
它是如何做到的?中断?完成?如何对守护进程线程进行编码,使其在终止时能够正常响应?
我只是写了下面的代码作为测试:
public class DaemonThreadPlay {
public static void main(String [] args) {
Thread daemonThread = new Thread() {
public void run() {
while (true) {
try {
System.out.println("Try block executed");
Thread.sleep(1000l);
} catch (Throwable t) {
t.printStackTrace();
}
}
}
@Override
public void finalize() {
System.out.println("Finalize method called");
}
};
daemonThread.setDaemon(true);
daemonThread.start();
try {
Thread.sleep(2500l);
} catch (Throwable t) {
//NO-OP
}
}
}
我将断点放在守护程序线程的 catch 块和 finalize 方法中。即使执行了 try 块,也未达到任何断点。显然,这段代码存在同步/计时问题,但我认为我们可以有把握地得出结论,守护进程线程不会在关闭时中断,也不一定调用它们的finize()方法。
您始终可以向 JVM 运行时添加关闭挂钩:
Thread shutdownHook = ... // construct thread that somehow
// knows about all the daemon threads
Runtime.getRuntime().addShutdownHook(shutdownHook);
您的关机挂钩显然可以执行“正常”关机所需的任何任务。
我认为你误解了守护进程线程是什么。
总而言之,它基本上意味着守护进程线程不应该执行任何 I/O 或持有任何资源。如果您违反了此基本规则,那么您的线程不符合成为守护程序线程的条件。
添加关闭钩子是确保在 JVM 终止之前调用代码的标准方法,但即使这样也不能 100% 保证 - 例如,您的 JVM 可能会崩溃,让操作系统以一种保护操作系统的方式整理资源,但很可能使您的应用程序处于不一致/错误状态。
系统检查点和恢复机制可以追溯到软件的早期(例如操作系统和批处理操作),不幸的是,这个轮子不断被重新发明,因为没有“银弹”方法(API)以足够通用的方式解决这个问题。