我有一个负责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
}
}
}
我在守护线程(daemon thread)的catch块和finalize方法中设置了断点,尽管try块已被执行,但两个断点都没有被触发。显然,这段代码存在同步/时间问题,但我认为我们可以得出结论:在关闭时不会中断守护线程,它们的finalize()方法也不一定被调用。
您可以始终向JVM Runtime添加一个shutdown hook:
Thread shutdownHook = ... // construct thread that somehow
// knows about all the daemon threads
Runtime.getRuntime().addShutdownHook(shutdownHook);
你的关闭挂钩可以执行所有必要的任务,以实现“优雅”的关闭。
System.gc()
,并且 JVM 选项 -XX:+DisableExplicitGC
没有设置,则守护线程将退出。这意味着垃圾回收器负责在所有用户线程完成后关闭守护线程。 - GeorgeExecutorService execPool = Executors.newSingleThreadExecutor(new ThreadFactory() {
@Override
public Thread newThread(Runnable runnable) {
Thread thread = Executors.defaultThreadFactory().newThread(runnable);
thread.setDaemon(true);
return thread;
}
});
在关闭钩子中调用ExecutorService的shutdown方法。
Runtime.getRuntime().addShutdownHook(....)
Executors.defaultThreadFactory()
只会返回一个 new DefaultThreadFactory()
。 - benez使用中断和加入:
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());
}
}