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

典型回答

在Java中有两类线程:User Thread(用户线程)、Daemon Thread(守护线程) 。用户线程一般用于执行用户级任务,而守护线程也就是“后台线程”,一般用来执行后台任务,守护线程最典型的应用就是GC(垃圾回收器)。

这两种线程其实是没有什么区别的,唯一的区别就是Java虚拟机在所有<用户线程>都结束后就会退出,而不会等<守护线程>执行完。

扩展知识

创建守护线程

我们可以通过使用setDaemon()方法通过传递true作为参数,使线程成为一个守护线程。我们必须在启动线程之前调用一个线程的setDaemon()方法。否则,就会抛出一个java.lang.IllegalThreadStateException。

可以使用isDaemon()方法来检查线程是否是守护线程。

/**
* @author Hollis
*/
public class Main {
  public static void main(String[] args) {
    Thread t1 = new Thread();
    System.out.println(t1.isDaemon());
    t1.setDaemon(true);
    System.out.println(t1.isDaemon());
    t1.start();
    t1.setDaemon(false);
  }
}

以上代码输出结果:

false
true
Exception in thread "main" java.lang.IllegalThreadStateException
at java.lang.Thread.setDaemon(Thread.java:1359)
at com.hollis.Main.main(Main.java:16)

我们提到,当JVM中只剩下守护线程的时候,JVM就会退出,那么写一段代码测试下:

/**
* @author Hollis
*/
public class Main {
  public static void main(String[] args) {
    Thread childThread = new Thread(new Runnable() {
      @Override
      public void run() {
        while (true) {
          System.out.println("I'm child thread..");
            try {
              TimeUnit.MILLISECONDS.sleep(1000);
            } catch (InterruptedException e) {
             e.printStackTrace();
            }
          }
        }
      });
    childThread.start();
    System.out.println("I'm main thread...");
  }
}

以上代码中,我们在Main线程中开启了一个子线程,在并没有显示将其设置为守护线程的情况下,他是一个用户线程,代码比较好理解,就是子线程处于一个while(true)循环中,每隔一秒打印一次I'm child thread..

输出结果为:

I'm main thread...
I'm child thread..
I'm child thread..
.....
I'm child thread..
I'm child thread..

我们再把子线程设置成守护线程,重新运行以上代码。

/**
* @author Hollis
*/
public class Main {
    public static void main(String[] args) {
    Thread childThread = new Thread(new Runnable() {
      @Override
      public void run() {
        while (true) {
            System.out.println("I'm child thread..");
          try {
              TimeUnit.MILLISECONDS.sleep(1000);
          } catch (InterruptedException e) {
             e.printStackTrace();
          }
        }
      }
    });
    childThread.setDaemon(true);
    childThread.start();
    System.out.println("I'm main thread...");
  }
}

以上代码,我们通过childThread.setDaemon(true);把子线程设置成守护线程,然后运行,得到以下结果:

I'm main thread...
I'm child thread..

子线程只打印了一次,也就是,在main线程执行结束后,由于子线程是一个守护线程,JVM就会直接退出了。

值得注意的是,在Daemon线程中产生的新线程也是Daemon的。

原文: https://www.yuque.com/hollis666/xkm7k3/dlg6vw