守护线程

定义
  在Java中有两类线程:User Thread(用户线程)、Daemon Thread(守护线程)
  用户线程: 是指用户自定义创建的线程,主线程停止,用户线程不会停止
  守护线程:为所有非守护线程提供服务的线程;换句话说,任何一个守护线程都是整个JVM中所有非守护线程的保姆;只要当前JVM实例中尚存在任何一个非守护线程没有结束,守护线程就全部工作只有当最后一个非守护线程结束时,守护线程随着JVM一 同结束工作。

如何使用

Thread t = new MyThread();
t.setDaemon(true);//设置当前线程为守护线程
t.start();

注意

  • thread.setDaemon(true)必须在thread.start()之前设置,否则会报出一个IllegalThreadStateException异常。你不能把正在运行的常规线程设置为守护线程。
  • 在守护线程中,编写代码要注意:守护线程不能持有任何需要关闭的资源,例如打开文件等,因为虚拟机退出时,守护线程没有任何机会来关闭文件,这会导致数据丢失。

特性

  1. 当 JVM 中不存在任何一个正在运行的非守护线程时,则 JVM 进程即会退出。也就是说当JVM中只有守护线程存在时JVM 会自动退出,守护线程终止。
  2. 在Daemon线程中产生的新线程也是Daemon的。
  3. 守护线程是对与整个JVM来说的,只要JVM中存在非守护线程,所有的守护线程就全部工作,只有当JVM中所有的非守护线程全部结束,此时守护线程才会终止(并不是调用它的父线程终止它就会终止)

特性分析

  • 特性2:在Daemon线程中产生的新线程也是Daemon的。
public class DaemonThread2 {
    public static void main(String[] args) throws InterruptedException {
        Thread t = new Thread(() -> {
            Thread innerThread = new Thread(() -> {
                try {
                    while (true) {
                        System.out.println("守护线程,执行心跳检测");
                        Thread.sleep(1_000);
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            });
            innerThread.start();
            try {
                Thread.sleep(1_000);
                System.out.println("用户线程 结束");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        t.setDaemon(true);
        t.start();
    }
}

运行结果为空

分析:线程t为守护线程,所以它的子线程innerThread 也是守护线程,当主线程终止时,jvm退出守护线程终止,所以没有数据打印出来

  • 特性3:守护线程是对与整个JVM来说的,只要JVM中存在非守护线程,所有的守护线程就全部工作,只有当JVM中所有的非守护线程全部结束,此时守护线程才会终止(并不是调用它的父线程终止它就会终止)
public class DaemonThread2 {
    public static void main(String[] args) throws InterruptedException {

        Thread t = new Thread(() -> {
            Thread innerThread = new Thread(() -> {
                try {
                    while (true) {
                        System.out.println("t0 守护线程,执行心跳检测");
                        Thread.sleep(1_000);
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            });
            innerThread.setDaemon(true);
            innerThread.start();
            try {
                Thread.sleep(1_000);
                System.out.println("t0 用户线程 结束");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });

        Thread t1 = new Thread(() -> {
            Thread innerThread = new Thread(() -> {
                try {
                    while (true) {
                        System.out.println("t1  守护线程,执行心跳检测");
                        Thread.sleep(1_000);
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            });
            innerThread.setDaemon(true);
            innerThread.start();
            try {
                Thread.sleep(3_000);
                System.out.println("t1 用户线程 结束");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        t1.start();
        t.start();
    }
}

运行结果:

java守护线程 性能消耗 线程守护线程_用户线程


分析:t0 t1 两个线程中都有一个守护线程执行心跳检测,当t0结束时t0的守护线程依然存在,直到t1也结束,整个程序中中不存在任何一个正在运行的非守护线程时,t0的守护线程才结束