什么是守护线程,它和普通线程有什么区别?

 作者简介:大家好,我是码炫码哥,前中兴通讯、美团架构师,现任某互联网公司CTO,兼职码炫课堂主讲源码系列专题


代表作:《jdk源码&多线程&高并发》,《深入tomcat源码解析》,《深入netty源码解析》,《深入dubbo源码解析》,《深入springboot源码解析》,《深入spring源码解析》,《深入redis源码解析》等


联系qq:184480602,加我进群,大家一起学习,一起进步,一起对抗互联网寒冬。码炫课堂的个人空间-码炫码哥个人主页-面试,源码等

回答

在 Java 语言中,线程分为两类:

  • 用户线程(User Thread)
  • 守护线程(Deamon Threa)

一般情况下,如果不做特殊配置,我们创建的线程或线程池都是用户线程,所以用户线程也被称之为普通线程,它一般用于执行用户级任务。

而守护线程则是一种比较特殊的线程,它一般都是为其他的线程服务,在后台默认完成一些系统服务,比如垃圾回收线程就是一个典型的守护线程。

守护线程和普通线程的区别有这么几点:

  1. 退出机制:普通线程会阻止 JVM 的退出,直到所有的普通线程执行完毕。而守护线程不会阻止 JVM 的退出。守护线程是为用户线程服务的,当一个应用中的所有用户线程都执行完成之后,应用程序也会结束运行,应用程序结束运行时是不会管守护线程是否正在运行。
  2. 用途和重要性:普通线程通常用于执行应用程序的核心功能,而守护线程则用于服务,比如资源管理或者监控之类的。

扩展知识

我们可以调用 setDaemon(true) 来设置某个线程为守护线程,但是它必须要放在线程的 start() 之前,否则程序会报错。

public class DaemonThreadTest {
    public static void main(String[] args) throws Exception {
        Thread thread = new Thread(() ->{
            System.out.println("我是码哥,这是码哥的 Java 面试题 600 讲!!!");
        });

        thread.start();
        thread.setDaemon(true);
    }
}

执行结果:

Exception in thread "main" java.lang.IllegalThreadStateException
  at java.base/java.lang.Thread.setDaemon(Thread.java:2239)
  at com.skjava.java.feature.DaemonThreadTest.main(DaemonThreadTest.java:10)

调用 isDaemon() 可以判断某个线程是否为守护线程:

public class DaemonThreadTest {
    public static void main(String[] args) throws Exception {
        Thread thread1 = new Thread(() ->{
            System.out.println("我是码哥,这是码哥的 Java 面试题 600 讲!!!");
        });

        Thread thread2 = new Thread(() ->{
            System.out.println("我是码哥,这是码哥的 Java 面试题 600 讲!!!");
        });

        thread1.setDaemon(true);

        System.out.println("thread1 是否为守护线程:" + thread1.isDaemon());
        System.out.println("thread2 是否为守护线程:" + thread2.isDaemon());
    }
}

执行结果:

thread1 是否为守护线程:true
thread2 是否为守护线程:false

码哥在上面提过,当应用程序中只剩下守护线程时,JVM 就会退出:

public class DaemonThreadTest {
    public static void main(String[] args) throws Exception {
        Thread thread1 = new Thread(() ->{
            for (int i = 1 ; i <= 10 ; i++) {
                System.out.println("我是守护线程,运行 " + i + "次..");

                try {
                    TimeUnit.MILLISECONDS.sleep(300);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        });
        thread1.setDaemon(true);

        Thread thread2 = new Thread(() ->{
            for (int i = 1 ; i <= 10 ; i++) {
                System.out.println("我是普通线程,运行 " + i + "次..");

                try {
                    TimeUnit.MILLISECONDS.sleep(100);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        });

        thread1.start();
        thread2.start();
    }
}

普通线程 for 循环 10 次,每次等待 100 毫秒,而守护线程 for 循环 10 次,每次等待 300 毫秒,运行结果如下:

普通线程执行了 10 次,而守护线程只执行了 4 次 JVM 就退出了。

如果我们在守护线程中创建线程呢,该线程是守护线程还是普通线程?

public class DaemonThreadTest {
    public static void main(String[] args) throws Exception {
        Thread thread1 = new Thread(() ->{
            Thread thread2 = new Thread(() -> {

            });
            System.out.println("thread2 守护线程子线程是守护线程:" + thread2.isDaemon());
        });
        thread1.setDaemon(true);
        thread1.start();

        TimeUnit.SECONDS.sleep(2);
    }
}

执行结果:

thread2 守护线程子线程是守护线程:true

所以守护线程中创建的子线程,默认情况下也属于守护线程

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值