一、说明
Java中的线程分为两类:一种是守护线程,一种是用户线程。平台我们经常用到的就是用户线程。用户线程和守护线程,从本质上来说并没有什么区别,唯一的不同之处就在于虚拟机的离开:如果用户线程已经全部退出运行了,只剩下守护线程存在了,虚拟机也就退出了。 因为没有了被守护者,守护线程也就没有工作可做了,也就没有继续运行程序的必要了也就是只要其它非守护线程运行结束了,即使守护线程的代码没有执行完,也会强制结束。 Java垃圾回收就是一个典型的守护线程。Tomcat 中的 Acceptor 和 Poller 线程都是守护线程,所以 Tomcat 接收到 shutdown 命令后,不会等待它们处理完当前请求。若要生成一个守护线程,只需线程在调用start之前,调用setDaemon(true)即可。
二、代码演示
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(() -> {
while (true) {
if (Thread.currentThread().isInterrupted()) {
break;
}
}
log.debug("结束");
}, "t1");
t1.setDaemon(true);
t1.start();
Thread.sleep(1000);
log.debug("结束");
/**
* 运行结果:
* 22:59:17.456 c.Test15 [main] - 结束
*/
}
如果t1不是守护线程,那么程序输出【c.Test15 [main] - 结束 】后就一个值循环线程t1中的while循环体,程序也不会停止下来。但是此时t1是守护线程,当主线程执行完后,守护线程立马就终止,所以线程内部的【结束】在整个程序结束后也不会被输出。注意,t1.setDaemon(true);必须在start之前执行,否则就会抛出IllegalThreadStateException异常。这通过setDaemon源码可以很简单的看出来。如果想知道某个线程是否是守护线程则通过isDaemon()方法即可得知。
public final void setDaemon(boolean on) {
//检查
checkAccess();
//判断线程是否是存活状态,如果是存活状态则抛出异常
if (isAlive()) {
throw new IllegalThreadStateException();
}
//Thread 中的成员daemon 设置为on
daemon = on;
}
public final boolean isDaemon() {
return daemon;
}
|