轻松理解Java守护线程

守护线程和非守护线程

什么是守护线程

之前的文章中提到过,在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
喜欢就支持一下吧
点赞0 分享