Java并发编程(八)——守护线程(Daemon)

252 阅读2分钟

在讲守护线程之前,需要先了解一个相对应的概念——用户线程。用户线程可以理解为系统的工作线程,用于处理业务上的操作。而守护线程,顾名思义,它负责守护系统,默默地在后台进行一些系统层面的处理。比如负责垃圾回收、JIT等的线程就可以称为守护线程。当用户线程全部结束,也就代表着系统没有任务需要处理了,系统可以退出了,当系统退出后守护线程的守护对象也就不存在了,守护线程没有继续运行的必要了。在一个Java应用内,如果系统中只剩守护线程在运行,虚拟机就会退出。

下面简单看一下守护线程的使用:

public class DaemonDemo {
    public static class DaemonT extends Thread {
        public void run() {
            while(true) {
                System.out.println("I'm alive.");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    
    public static void main (String[] args) throws InterruptedException(){
        DaemonT t = new DaemonT();
        t.setDaemon(true);
        t.start();
        
        Thread.sleep(2000);
    }
}

上述代码中,将t设置为守护线程。需要注意的是,设置守护线程要在调用start()之前,否则会抛出异常。以下是JDK中设置守护线程相关的代码:

public final void setDaemon(boolean on) {
    checkAccess();
    // 如果线程已经开始运行,将抛出异常
    if (isAlive()) {
        throw new IllegalThreadStateException();
    }
    daemon = on;
}

线程在抛出这个异常后依然会继续运行,不过是作为用户线程。因此如果忽略了这个异常,可能会导致程序不能正常退出。

在之前的例子中,由于t被设为守护线程,系统中只有主线程main作为用户线程,因此在main线程休眠2秒并退出后,整个程序也随之结束。但如果没有把t设置为守护线程,main结束后t依然会继续运行,程序也就无法结束。