ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

InheritableThreadLocal源码阅读

2022-02-23 10:33:01  阅读:176  来源: 互联网

标签:inheritableThreadLocals Thread ThreadLocalMap ThreadLocal 源码 线程 阅读 InheritableTh


说明

继前面《ThreadLocal源码阅读》知道ThreadLocal原理是获取当前线程Thread的一个Map,通过Entry封装 key为ThreadLocal对象自身 value为我们的值。但是ThreadLocal本身不是子线程共享的。InheritableThreadLocal就是为了解决子线程共享问题

如何实现子线程共享

我们知道线程变量都是通过Thread对象的threadLocals存储,其实除了这个线程对象还提供子线程共享的Map inheritableThreadLocals,创建子线程此变量会默认复制一份父线程此Map,注:是复制并不是继承 所以还是线程安全的,子线程set值并不会影响父线程或者其他子线程的值

 /*  当前线程共享 子线程并不能共享
     * by the ThreadLocal class. */
    ThreadLocal.ThreadLocalMap threadLocals = null;

    /*
     * 
     * 创建线程时子线程会复制一份
     */
    ThreadLocal.ThreadLocalMap inheritableThreadLocals = null;

继承关系

 

重写的三个核心方法

    /**
     * 复制父类ThreadLocalMap的时候调用 原路复制不做任何处理
     * @param parentValue
     * @return
     */
    protected T childValue(T parentValue) {
        return parentValue;
    }

    /**
     * 重写getMap获取线程对象的inheritableThreadLocals 后续复制也是复制此对象 具体可以看ThreadLocal源码
     *
     * @param t the current thread
     */
    ThreadLocal.ThreadLocalMap getMap(Thread t) {
        return t.inheritableThreadLocals;
    }

    /**
     *
     * @param t the current thread
     * @param firstValue value for the initial entry of the table.
     */
    void createMap(Thread t, T firstValue) {
        t.inheritableThreadLocals = new ThreadLocal.ThreadLocalMap(this, firstValue);
    }

如何实现复制

<1>

 //<2>构造函数实现复制
        Thread thread=new Thread(new Runnable() {
            @Override
            public void run() {

            }
        });

<2>

public Thread(Runnable target) {
            //<3>
            init(null, target, "Thread-" + nextThreadNum(), 0);
        }

<3>

private void init(ThreadGroup g, Runnable target, String name,
        long stackSize) {
            //<4>最后一个参数为true表示复制父线程 
            init(g, target, name, stackSize, null, true);
        }

<4>

   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) {
          
            if (security != null) {
                g = security.getThreadGroup();
            }

       
            if (g == null) {
                g = parent.getThreadGroup();
            }
        }

      
        g.checkAccess();

      
        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);
        //inheritThreadLocals为true 同时inheritableThreadLocals不为空则复制父线程的
        if (inheritThreadLocals && parent.inheritableThreadLocals != null)
            //<5>复制父线程的inheritableThreadLocals
            this.inheritableThreadLocals =
                    ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);
        /* Stash the specified stack size in case the VM cares */
        this.stackSize = stackSize;

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

<5>

 static ThreadLocal.ThreadLocalMap createInheritedMap(ThreadLocal.ThreadLocalMap parentMap) {
        //<6>复制
        return new ThreadLocal.ThreadLocalMap(parentMap);
    }

<6>

 private ThreadLocalMap(ThreadLocal.ThreadLocalMap parentMap) {
        ThreadLocal.ThreadLocalMap.Entry[] parentTable = parentMap.table;
        int len = parentTable.length;
        setThreshold(len);
        table = new ThreadLocal.ThreadLocalMap.Entry[len];
        //遍历inheritableThreadLocals的值
        for (int j = 0; j < len; j++) {
            ThreadLocal.ThreadLocalMap.Entry e = parentTable[j];
            if (e != null) {
                //这里获取到的是InheritableThreadLocal
                ThreadLocal<Object> key = (ThreadLocal<Object>) e.get();
                if (key != null) {
                    //调用childValue 被重写
                    Object value = key.childValue(e.value);
                    //用新的Entry封装保存到当前map
                    ThreadLocal.ThreadLocalMap.Entry c = new ThreadLocal.ThreadLocalMap.Entry(key, value);
                    int h = key.threadLocalHashCode & (len - 1);
                    while (table[h] != null)
                        h = nextIndex(h, len);
                    table[h] = c;
                    size++;
                }
            }
        }
    }

 

标签:inheritableThreadLocals,Thread,ThreadLocalMap,ThreadLocal,源码,线程,阅读,InheritableTh
来源: https://www.cnblogs.com/LQBlog/p/15926150.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有