C/C++教程

InheritableThreadLocal源码阅读

本文主要是介绍InheritableThreadLocal源码阅读,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

说明

继前面《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++;
                }
            }
        }
    }

 

这篇关于InheritableThreadLocal源码阅读的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!