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块,也没有达到断点。 显然这段代码有同步/计时问题,但我认为我们可以安全地得出结论,守护程序线程在关闭时不会被中断,也不一定会调用它们的finalize()方法。

您始终可以向JVM运行时添加关闭挂钩:

 Thread shutdownHook = ... // construct thread that somehow // knows about all the daemon threads Runtime.getRuntime().addShutdownHook(shutdownHook); 

您的关闭钩子显然可以执行“正常”关闭所需的任何任务。

我想你误解了一个守护程序线程是什么。

看看java中的守护程序线程是什么

总之,它基本上意味着守护程序线程不应该执行任何I / O或持有任何资源。 如果您违反了这个基本规则,那么您的线程就不能成为守护程序线程。

添加关闭挂钩是确保在JVM终止之前调用代码的标准方法,但即使这样也不是100%保证 – 例如,您的JVM可能会崩溃,让操作系统以保护操作系统的方式整理资源,但很可能使您的应用程序处于不一致/错误状态。

系统检查点和恢复机制可以追溯到软件的早期阶段(例如操作系统和批处理操作),不幸的是,这个轮子不断重新发明,因为没有“银弹”方法(API)可以解决这个问题。通用的方式。

AFAIK,Daemon线程并不真正用于主流I / O工作。 如果所有线程都已完成,JVM可能会突然关闭所有守护程序线程。 可能需要解决的问题是创建一个如下所示的ExecutorService:

 ExecutorService execPool = Executors.newSingleThreadExecutor(new ThreadFactory() { @Override public Thread newThread(Runnable runnable) { Thread thread = Executors.defaultThreadFactory().newThread(runnable); thread.setDaemon(true); return thread; } }); 

从Shutdown hook调用executorservice shutdown方法。

 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()); } }