• 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操作或者其他持久化操作并不合理,这里需要注意下

  • 相关阅读:
    ES6 基础
    JavaScript 基础
    Java 虚拟机
    MinIO 搭建使用
    .NET 半天搭建Jenkins持续集成与自动化部署系统
    驱动领域DDD的微服务设计和开发实战
    走向架构师必备的技能
    分布式系统与消息的投递¶
    求数组的子数组之和的最大值
    KVO初探
  • 原文地址:https://www.cnblogs.com/zhoutao825638/p/10393208.html
Copyright © 2020-2023  润新知