玖叶教程网

前端编程开发入门

面试官:何谓守护线程?简述守护线程创建流程?

线程设置为守护线程的过程之源码分析


1 守护线程和用户线程的区别

1.1线程分为用户线程和守护线程,默认都是用户线程

1.2虚拟机必须确保用户线程执行完毕,但是不会等待守护线程执行完毕

1.3守护线程使用场景:操作日志 监控内存 垃圾回收

1.4当用户线程结束,守护线程也会跟着结束




2 守护线程是怎么创建的

2.1设置为守护线程的方法setDaemon,默认是传false,默认是用户线程,调用这个方法即可将线程设置为守护线程

public final void setDaemon(boolean on) {
    checkAccess();
    if (isAlive()) {
        throw new IllegalThreadStateException();
    }
    daemon = on;
}

3 在设置线程为守护的线程的过程,会检验这个线程是否已经启动,已经是否有权限修改

checkAccess(); 校验权限

 public final void checkAccess() {
        SecurityManager security = System.getSecurityManager();
        if (security != null) {
            security.checkAccess(this);
        }
    }

判断线程是否存活,因此要在启动之前设置守护线程标识,如果已经启动则无法设置,抛出异常

throw new IllegalThreadStateException();

public final native boolean isAlive();

守护线程和用户线程的初始化过程都是一模一样的,相同的init方法,并默认设置为用户线程

线程在初始化的时候,会调用判断,是否是守护线程,默认是false,而且此时一定是false,创建对象的过程init方法如下:

private void init(ThreadGroup g, Runnable target, String name,
                      long stackSize, AccessControlContext acc,
                      boolean inheritThreadLocals) {
        if (name == null) {
            throw new NullPointerException("name cannot be null");
        }

        this.name = name;

        Thread parent = currentThread();
        SecurityManager security = System.getSecurityManager();
        if (g == null) {
            /* Determine if it's an applet or not */

            /* If there is a security manager, ask the security manager
               what to do. */
            if (security != null) {
                g = security.getThreadGroup();
            }

            /* If the security doesn't have a strong opinion of the matter
               use the parent thread group. */
            if (g == null) {
                g = parent.getThreadGroup();
            }
        }

        /* checkAccess regardless of whether or not threadgroup is
           explicitly passed in. */
        g.checkAccess();

        /*
         * Do we have the required permissions?
         */
        if (security != null) {
            if (isCCLOverridden(getClass())) {
                security.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION);
            }
        }

        g.addUnstarted();

        this.group = g;
        this.daemon = parent.isDaemon();
        this.priority = parent.getPriority();
        if (security == null || isCCLOverridden(parent.getClass()))
            this.contextClassLoader = parent.getContextClassLoader();
        else
            this.contextClassLoader = parent.contextClassLoader;
        this.inheritedAccessControlContext =
                acc != null ? acc : AccessController.getContext();
        this.target = target;
        setPriority(priority);
        if (inheritThreadLocals && parent.inheritableThreadLocals != null)
            this.inheritableThreadLocals =
                ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);
        /* Stash the specified stack size in case the VM cares */
        this.stackSize = stackSize;

        /* Set thread ID */
        tid = nextThreadID();
    }


判断是否为守护线程的方法isDaemon

/**
     * Tests if this thread is a daemon thread.
     *
     * @return  <code>true</code> if this thread is a daemon thread;
     *          <code>false</code> otherwise.
     * @see     #setDaemon(boolean)
     */
    public final boolean isDaemon() {
        return daemon;
    }



打断点测试

初始化时,赋值 this.daemon = parent.isDaemon();



创建对象成功之后,调用方法赋值,标记为守护线程,修改Thread的对象的值



初始化方法都是在构造对象的时候使用,没有其他的地方调用执行



那么问题来了?初始花的时候为什么是调用判断是否守护方法,而不是直接赋值为false? ?


总结:个人认为守护线程和用户线程在创建的过程没有区别,如果是守护线程,在启动之前对线程对象修改了值,标记为守护线程,

那么这个线程优先级低,同时若JVM中所有的用户线程执行结束,则守护线程会跟随停止,不能保证守护线程的任务正常结束

那么是否有一种场景,我希望他是守护线程,同时我还希望守护线程的任务正常结束,在jvm关闭之前完成任务?


这个答案下期见



以上文章为个人学习记录,若有任何不正确的地方,欢迎指正!

发表评论:

控制面板
您好,欢迎到访网站!
  查看权限
网站分类
最新留言