假设情景:
我有一个守护程序线程负责一些I / O,主线程完成并返回,并且JVM决定终止我的守护程序线程。
它是如何做到的?打断?最终确定?如何对我的守护程序线程进行编码,以便在终止时对它做出正确的反应?
答案 0 :(得分:11)
我刚刚编写了以下代码作为测试:
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);
你的关机钩子显然可以执行“正常”关闭所需的任何任务。
答案 1 :(得分:5)
我认为你误解了一个守护程序线程是什么。
请参阅what is a daemon thread in java
总之,它基本上意味着守护程序线程不应该执行任何I / O或持有任何资源。如果您违反了这个基本规则,那么您的线程就不能成为守护程序线程。
添加关闭挂钩是确保在JVM终止之前调用代码的标准方法,但即使这样也不是100%保证 - 例如,您的JVM可能会崩溃,让操作系统以一种方式整理资源保护操作系统,但很可能使您的应用程序处于不一致/错误状态。
系统检查点和恢复机制可以追溯到软件的早期阶段(例如操作系统和批处理操作),不幸的是,这个轮子不断重新发明,因为没有“银弹”方法(API)可以解决这个问题。足够通用的问题。
答案 2 :(得分:4)
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(....)
答案 3 :(得分:1)
使用中断和加入:
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());
}
}