菜鸟笔记
提升您的技术认知

关于守护线程

线程分为两种,用户线程和守护线程。

了解守护线程之前先了解一下常见的用户线程。重新启动一个线程有两种方法。一种是定义一个类例如userThread实现Runable接口并重写run方法,然后通过如下方式启动线程。

Thread th = new Thread(new userThread());
th.start();

另一种本质上也一样,不过不需要定义一个实体类,通过匿名类也可以实现,如下:

Thread th = new Thread(){
    @Override
    public void run(){
        System.out.println("-");
    }
};
th.start()/或者使用线程池
或者直接
new Thread(){
    @Override
    public void run(){
        System.out.println("-");
    }
}.start();
启动一个线程

其实守护线程和用户线程区别不大,可以理解为特殊的用户线程。特殊就特殊在如果程序中所有的用户线程都退出了,那么所有的守护线程就都会被杀死,很好理解,没有被守护的对象了,也不需要守护线程了。启动守护线程也有两种方法,先来看看怎么启动守护线程 。

最常用的一种是通过将用户线程转换为守护线程来启动线程从而启动守护线程。

thread.setDaemon(true);

这样可以设置该线程为守护线程,值得注意的是必须在线程启动start()方法之前设置。

还有一个启动守护线程的方法就是利用Timer和TimerTask。Timer是JDK提供的定时器工具,使用时会在主线程之外单独起一个线程执行指定的任务。Timer timer = new Timer()启动的是用户线程,而Timer timer = new Timer(true)启动的就是守护线程。TimerTask是一个实现了Runnable接口的抽象类,配合Timer使用可以看做被Timer执行的任务,即启动的线程。用法示例如下:

Timer timer = new Timer()启动用户线程,由于都是用户线程,主线程退出后新启动的用户线程还继续执行,所以最后运行结果都打印出来了。

 Timer timer = new Timer(true)启动守护线程,主线程退出后新启动的守护线程被杀死,所以最后运行结果都只打印出主线程的语句,守护线程中语句不打印。

还有一个值得注意的是守护线程中产生的线程都是守护线程,实例如下:

定义两个实现了Runnable的类,并在Daemon线程中启动DaemonSpawn线程。

 

如果主函数中将Daemon设为守护线程并启动,用TimeUnit.SECONDS.sleep(1)让主线程睡眠即不退出,就给了守护线程执行并打印语句的时间

 运行结果如下:

 如果主函数中将TimeUnit.SECONDS.sleep(1)去掉,主线程退出后所有的守护线程就都被杀死,不会打印语句,就只有主线程的语句打印。主函数和运行结果如下: