InheritableThreadLocal源码阅读

说明

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

如何实现子线程共享

我们知道线程变量都是通过Thread对象的threadLocals存储,其实除了这个线程对象还提供子线程共享的Map inheritableThreadLocals,创建子线程此变量会默认复制一份父线程此Map,注:是复制并不是继承 所以还是线程安全的,子线程set值并不会影响父线程或者其他子线程的值,默认是浅克隆,如果是操作ThreadLocal保存的引用对象则会实现修改,我们可以在childvalue自定义实现深克隆

 /*  当前线程共享 子线程并不能共享
     * 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++;
                }
            }
        }
    }

浅克隆的体现

package other.sort;

import java.io.IOException;

/**
 * @author liqiang
 * @date 2022/2/23
 */
public class psvm {

     String name;
     String age;

    public psvm(String name, String age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public String toString() {
        return "psvm{" +
                "name='" + name + '\'' +
                ", age='" + age + '\'' +
                '}';
    }

    public static void main(String[] args) throws Exception {
        ThreadLocal<psvm> threadLocal = new InheritableThreadLocal();
        psvm zs = new psvm("zs", "12");
        threadLocal.set(zs);
        new Thread(()->{
            psvm psvm = threadLocal.get();
            System.out.println(threadLocal.get());
            psvm.age= "13";
        }).start();
        Thread.sleep(3000);
        System.out.println("main"+threadLocal.get());
        System.in.read();
    }
}

 

posted @ 2022-02-23 10:24  意犹未尽  阅读(77)  评论(0编辑  收藏  举报