Java中的守护线程

守护线程的概念

在java中有两种线程,守护线程和非守护线程,其两者并没有本质的区别,唯一的区别就是当前的用户线程退出的时候,若只存在唯一的A线程,若A线程为守护线程,那么JVM将会直接退出,否则JVM不会退出而是等待A线程执行完成后退出.

如何创建守护线程

这里我们创建一个基本的需求,在Main线程中其中一个线程A,我们分别设置A线程是守护线程和非守护线程,来观察执行的结果.

设置一个线程为守护线程则非常的简单,只要在线程启动之前,也就是调用其start()方法之前,调用其setDaemon方法即可. 其方法定义如下:

  • 通过分析这部分的源码可以看到,设置的daemon的时候首先会调用checkAccess()方法,这个方法会检查当前线程是否能被修改,也就是是否已经启动,如果已经启动,再调用setDaemon()方法的话,那么就会抛出IllegalThreadStateException,这也是为什么必须在start()方法调用之前设置的原因.

  • 可以看到线程最后设置daemon变量为on,那么跟踪daemon变量,其定义为默认为false级非守护线程

        /* Whether or not the thread is a daemon thread. */
        private boolean     daemon = false;
    
  /**
     * Marks this thread as either a {@linkplain #isDaemon daemon} thread
     * or a user thread. The Java Virtual Machine exits when the only
     * threads running are all daemon threads.
     *
     * <p> This method must be invoked before the thread is started.
     *
     * @param  on
     *         if {@code true}, marks this thread as a daemon thread
     *
     * @throws  IllegalThreadStateException
     *          if this thread is {@linkplain #isAlive alive}
     *
     * @throws  SecurityException
     *          if {@link #checkAccess} determines that the current
     *          thread cannot modify this thread
     */
    public final void setDaemon(boolean on) {
        checkAccess();
        if (isAlive()) {
            throw new IllegalThreadStateException();
        }
        daemon = on;
    }

创建示例代码

package com.zhoutao.demo.thread;

import java.util.concurrent.TimeUnit;

/** 守护线程 */
public class DaemonThread {
  public static void main(String[] args) {
    Thread thread =
        new Thread() {
          @Override
          public void run() {
            while (true) {
              try {
                System.out.println("exec sub thread....");
                TimeUnit.SECONDS.sleep(1);
              } catch (InterruptedException e) {
                e.printStackTrace();
              }
            }
          }
        };
    // 设置参数修改为true 或者 false
    // 若设置为守护线程,那么当钱线程组不存在activeThread的线程的时候,程序将退出
    thread.setDaemon(false);
    thread.start();
    System.out.println("Main线程已经执行完成");
  }
}

这里通过 thread.setDaemon(true); 将线程设置为了非守护线程,当Main主线程执行完成的时候,子线程thread会继续执行,每隔1s中打印exec sub thread....,执行结果如下:

线程已经执行完成
exec sub thread....
exec sub thread....
exec sub thread....
exec sub thread....
exec sub thread....

这里则验证因为还存在非守护线程,所以JVM不会退出,会继续执行下去

下面我们设置该线程为守护线程,其结果为

线程已经执行完成
exec sub thread....

Process finished with exit code 0

可以明确的看到现成的退出code=0,说明当Main执行完成之后,JVM中并不存在非守护线程,所以JVM直接退出了

说明

由于我们并不知道线程组(ThreadGroup) 中的其他线程情况,因此我们也无法确定到JVM什么时候会退出,所以在守护线程中读写文件,进行IO操作或者其他持久化操作并不合理,这里需要注意下

posted @ 2019-02-17 23:10  燕归来兮  阅读(484)  评论(0编辑  收藏  举报