2-3 用户线程和守护线程

发布时间 2023-03-27 13:33:21作者: ShaunY

用户线程 vs 守护线程

Java 线程分为用户线程和守护线程,一般情况下不做特别说明配置,默认都是用户线程****。用户线程和守护线程是交替存在的

用户线程

是系统的工作线程,它会完成这个程序需要完成的业务操作。比如最基本的 main 方法,就是一个用户线程

public class DaemonDemo {
    public static void main(String[] args) {
    
    }
}

守护线程

是一种特殊的线程,为其它线程服务的,在后台默默地完成一些系统性的服务,比如垃圾回收线程就是最典型的例子

守护线程作为一个服务线程,没有服务对象就没有必要继续运行了,如果用户线程全部结束了,意味着程序需要完成的业务操作已经结束了,系统可以退出了。所以假如当系统只剩下守护线程的时候,java 虚拟机会自动退出

用户线程 vs 守护线程

有一个方法可以判断线程是否为守护线程

/**
 * Tests if this thread is a daemon thread.
 *
 * @return  <code>true</code> if this thread is a daemon thread;
 *          <code>false</code> otherwise.
 * @see     #setDaemon(boolean)
 */
public final boolean isDaemon() {
    return daemon;
}
  • 用户线程例子

    由于用户线程是独立的,所以互不干扰,比如在 main 线程结束之后,用户设置的线程还可以单独存在:

    public class DaemonDemo {
        public static void main(String[] args) {
            Thread t1 = new Thread(()->{
                System.out.println(Thread.currentThread().getName()+"\t 开始运行, "+
                        (Thread.currentThread().isDaemon()?"守护线程":"用户线程"));
                while(true){
    
                }
            },"t1");
            t1.start();
            try{
                TimeUnit.SECONDS.sleep(3);
            }catch(InterruptedException e){
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName()+"\t ----end 主线程");
        }
    }
    

    输出结果

    t1	 开始运行, 用户线程
    main	 ----end 主线程
    

    实际上,如果不主动结束运行的话,t1 还是会一直执行,哪怕 main 线程已经之行结束了

  • 守护线程例子

    public class DaemonDemo {
        public static void main(String[] args) {
            Thread t1 = new Thread(()->{
                System.out.println(Thread.currentThread().getName()+"\t 开始运行, "+
                        (Thread.currentThread().isDaemon()?"守护线程":"用户线程"));
                while(true){
    
                }
            },"t1");
            t1.setDaemon(true);
            t1.start();
            try{
                TimeUnit.SECONDS.sleep(3);
            }catch(InterruptedException e){
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName()+"\t ----end 主线程");
        }
    }
    

    将 t1 设置为守护线程,根据运行结果来看,当 main 线程(用户线程)执行结束,t1 也随之结束。

    输出结果:

    t1	 开始运行, 守护线程
    main	 ----end 主线程
    

小总结

  1. 如果用户线程全部结束意味着程序需要完成的业务操作己经结束了,守护线程随着 JVM 一同结束工作

  2. setDaemon(true) 方法必须在 start() 之前设置,否则报 IllegalThreadStateException 异常

    image