守护线程和非守护线程
什么是守护线程
之前的文章中提到过,在Java中有两类线程:User Thread
(用户线程)、Daemon Thread
(守护线程)。
用户线程和守护线程两者几乎没有区别,唯一的不同之处就在于虚拟机的离开:如果用户线程已经全部退出运行了,只剩下守护线程存在了,虚拟机也就退出了。
最经典的守护线程使用就是负责GC的线程。只要用户线程还在,他就会认认真真的执行自己的工作。
如何创建守护线程
将线程转换为守护线程可以通过调用Thread
对象的setDaemon(true)
方法来实现。在使用守护线程时需要注意一下几点:
(1) thread.setDaemon(true)
必须在thread.start()
之前设置,否则会跑出一个IllegalThreadStateException
异常。你不能把正在运行的常规线程设置为守护线程。
public class Test {
public static void main(String[] args) {
Thread t = new Thread(()->{
while(true){
System.out.println("我是守护线程t,我在运行");
}
});
t.setDaemon(true);
t.start();
// try {
// TimeUnit.SECONDS.sleep(1);
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
}
}
//这样执行起来什么也打印不了,但如果把注释去掉,让主线程停一秒就会持续打印。
复制代码
(2) 在守护线程线程中产生的新线程也是守护线程。
public class Test {
public static void main(String[] args) {
Thread t = new Thread(()->{
Thread a = new Thread(()->{
while (true){
System.out.println("我是线程a,我在运行");
}
});
a.start();
});
t.setDaemon(true);
t.start();
// try {
// TimeUnit.SECONDS.sleep(1);
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
}
}
//这样执行起来什么也打印不了,但如果把注释去掉,让主线程停一秒就会持续打印。这就证明了a也是守护线程
复制代码
(3) 守护线程应该永远不去访问固有资源,如文件、数据库,因为它会在任何时候甚至在一个操作的中间发生中断。
另外 调用thread
对象的IsDaemon()可以获得该对象是否为守护线程。
public static void main(String[] args) {
Thread t = new Thread(()->{
Thread a = new Thread(()->{
while (true){
//System.out.println("我是线程a,我在运行");
}
});
System.out.println(a.isDaemon());
a.setDaemon(false);
System.out.println(a.isDaemon());
a.start();
});
t.setDaemon(true);
t.start();
try {
TimeUnit.MILLISECONDS.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//打印结果是true和false。a可以一直运行
复制代码
但是在业务中,我基本上没使用过守护线程,我觉得他是一个了解了解就好的知识点。
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END