Java多线程编程核心技术(第3版)
上QQ阅读APP看书,第一时间看更新

1.15 守护线程

Java中有两种线程,一种是用户线程,也称非守护线程;另一种是守护线程。

什么是守护线程?守护线程是一种特殊的线程,当进程中不存在非守护线程时,则守护线程自动销毁。典型的守护线程就是垃圾回收线程,当进程中没有非守护线程了,则垃圾回收线程也就没有存在的必要,自动销毁。用一个比较通俗的比喻来解释一下“守护线程”,任何一个守护线程都可以看作整个JVM中所有非守护线程的“保姆”,只要当前JVM实例中有任何一个非守护线程没有结束(好比幼儿园中有小朋友),那么守护线程(也就是保姆)就要工作,只有当最后一个非守护线程结束时(好比幼儿园中没有小朋友了),守护线程(也就是保姆)才会随着JVM一同结束工作。守护Daemon线程的作用是为其他线程的运行提供便利服务,最典型的应用就是GC(垃圾回收器)。综上所述,当最后一个用户线程销毁了,守护线程会退出,进程也随之结束。

主线程main在本节中属于用户线程,凡是调用setDaemon(true)代码并且传入true值的线程才是守护线程。

创建项目daemonThread,文件MyThread.java代码如下:


package testpackage;

public class MyThread extends Thread {
private int i = 0;

@Override
public void run() {
    try {
        while (true) {
            i++;
            System.out.println("i=" + (i));
            Thread.sleep(1000);
        }
    } catch (InterruptedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}
}

文件Run.java代码如下:


package test.run;

import testpackage.MyThread;

public class Run {
public static void main(String[] args) {
    try {
            MyThread thread = new MyThread();
            thread.setDaemon(true);
            thread.start();
            Thread.sleep(5000);
            System.out.println("我离开thread对象也不再打印了,也就是停止了!");
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
}
}

图1-69 最后一个用户线程销毁守护线程也退出了

程序运行结果如图1-69所示。

要在执行start()方法之前执行setDaemon(boolean)方法,不然会出现异常,示例代码如下:


package test.run;

import testpackage.MyThread;

public class Run2 {
    public static void main(String[] args) {
        MyThread thread = new MyThread();
        thread.start();
        thread.setDaemon(true);
    }
}

程序运行出现异常如下:


Exception in thread "main" java.lang.IllegalThreadStateException
    at java.lang.Thread.setDaemon(Thread.java:1275)
    at test.run.Run2.main(Run2.jva:9)