Java JVM如何终止守护进程线程?或者如何编写优雅终止的守护进程线程
假设情景:Java JVM如何终止守护进程线程?或者如何编写优雅终止的守护进程线程,java,multithreading,jvm,daemon,Java,Multithreading,Jvm,Daemon,假设情景: 我有一个守护进程线程负责一些I/O,主线程完成并返回,JVM决定终止我的守护进程线程 它是如何做到这一点的?打断最终确定?如何对守护进程线程进行编码,使其在终止时能够正常反应?我刚刚编写了以下代码作为测试: public class DaemonThreadPlay { public static void main(String [] args) { Thread daemonThread = new Thread() { publi
我有一个守护进程线程负责一些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块,也未到达断点。显然,这段代码存在同步/计时问题,但我认为我们可以安全地得出结论,守护进程线程在关闭时不会中断,也不一定会调用它们的finalize()方法
您始终可以向JVM运行时添加关闭挂钩:
Thread shutdownHook = ... // construct thread that somehow
// knows about all the daemon threads
Runtime.getRuntime().addShutdownHook(shutdownHook);
显然,关闭钩子可以完成“正常”关闭所需的任何任务。AFAIK,守护进程线程并不真正用于主流I/O工作。如果所有线程都已完成,JVM可能会突然关闭所有守护进程线程。针对您的需求,可能的解决方法是创建一个Executor服务,如下所示:
ExecutorService execPool = Executors.newSingleThreadExecutor(new ThreadFactory() {
@Override
public Thread newThread(Runnable runnable) {
Thread thread = Executors.defaultThreadFactory().newThread(runnable);
thread.setDaemon(true);
return thread;
}
});
从关闭挂钩调用executorservice关闭方法
Runtime.getRuntime().addShutdownHook(....)
使用中断和连接:
class Daemon extends Thread {
public void run() {
while (true) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
System.out.println(e);
break;
}
}
System.out.println("exit run()");
}
}
public class So8663107 {
public static void main(String[] arguments) throws InterruptedException {
System.out.println(Thread.activeCount());
Daemon daemon = new Daemon();
daemon.setDaemon(true);
daemon.start();
Thread.sleep(2500);
System.out.println(Thread.activeCount());
daemon.interrupt();
daemon.join();
System.out.println(Thread.activeCount());
}
}
我想你误解了什么是守护线程 看 总之,它基本上意味着守护进程线程不应该执行任何I/O或持有任何资源。如果您违反了这个基本规则,那么您的线程就没有资格成为守护进程线程 添加关机挂钩是确保在JVM终止之前调用代码的标准方法,但即使这样也不能100%保证—例如,JVM可能会崩溃,让操作系统以保护操作系统的方式整理资源,但很可能会使应用程序处于不一致/错误的状态
系统检查点和恢复机制可以追溯到软件的早期(例如操作系统和批处理操作),不幸的是,由于没有“银弹”方法(API),这个轮子不断被重新发明它以一种非常通用的方式解决了这个问题。我喜欢关机挂钩。在寻找获取活动线程的方法时可以找到它。必须遍历数组以检查至少一个用户线程
我认为关机挂钩是最好的解决方案,以前从未了解过此功能。我想我将在我的主类中保留对我的关闭钩子的引用,并在关闭钩子中保留我的守护进程线程的集合。那我就可以打断他们了。一旦实现了我的代码,我将尝试发布它。如果显式调用
System.gc()
,并且未设置JVM选项-XX:+DisableExplicitGC
,则守护进程线程将退出。这意味着垃圾收集器负责在所有用户线程完成后关闭守护进程线程。您可以做的另一件事是引入finally块,无论try-catch块内发生什么,都保证调用它!通过这种方式,您可以关闭守护进程线程打开的任何资源,并在其中实现任何优雅的终止@熟练工人3小心不要草率下结论。当JVM在可视化调试期间停止时,很可能根本不会命中断点,因为JVM已经与调试器断开连接(我用IntelliJ IDEA目睹了这种行为)。我认为您不理解这个问题。我不想中断我的守护进程线程。我想知道JVM是如何终止它们的,以及如何处理它们。对不起,我试图回答:“我如何对我的守护进程线程进行编码,使其能够优雅地终止?”你看了源代码了吗?@StephenC,我没有想到这一点,肯定会给出一个明确的答案(尽管不一定是有用的答案)。然而,我个人并没有足够的勇气去尝试,也不指望其他人去尝试。好吧,让我更明确一点。回答这样一个问题的最好方法是查看源代码,或者至少是Java代码。总的来说,它很容易阅读和评论。(我不明白一个问题的确定答案如何不如一个非确定答案有用……特别是如果你是阅读代码的人!)告诉OP看源代码不是答案。这显示了特定的实现,而不是API要求。文档有它的位置。守护进程线程不应该执行IO或保存资源的说法的依据是什么?遵循提供的链接,您将获得一些见解。对不起,我不同意。只要理解一个守护进程线程可以在处理过程中被杀死,就不会有危险,除非你知道一些关于java资源泄漏的事情,我不知道。如果守护进程线程拥有数百个资源,终止JVM是疯狂的,更糟糕的是,当它处于一系列关键的写操作的中间时,就会发生关闭。你实际上是在冒应用程序一致性的风险。您也不同意Brian Goetz的观点,他写了“Java并发性在实践中”。。。不同意是可以的,但是我认为在少数情况下你可能是对的。你的newThread方法确实每次都会创建一个新的线程工厂。调用Executors.defaultThreadFactory()
只会返回一个新的defaultThreadFactory()