ThreadLocal和InheriableThreadLocal

示意图:

threadLocal.png

关键代码

Thread.java

    /* ThreadLocal values pertaining to this thread. This map is maintained
     * by the ThreadLocal class. */
    ThreadLocal.ThreadLocalMap threadLocals = null;

    /*
     * InheritableThreadLocal values pertaining to this thread. This map is
     * maintained by the InheritableThreadLocal class.
     */
    ThreadLocal.ThreadLocalMap inheritableThreadLocals = null;

threadLocals,inheritableThreadLocals为ThreadLocal.ThreadLocalMap对象(类HashMap(存储结构不大一样),元素Entry集成弱引用)

ThreadLocal.ThreadLocalMap

   static class ThreadLocalMap {

        /**
         * The entries in this hash map extend WeakReference, using
         * its main ref field as the key (which is always a
         * ThreadLocal object).  Note that null keys (i.e. entry.get()
         * == null) mean that the key is no longer referenced, so the
         * entry can be expunged from table.  Such entries are referred to
         * as "stale entries" in the code that follows.
         */
        static class Entry extends WeakReference> {
            /** The value associated with this ThreadLocal. */
            Object value;

            Entry(ThreadLocal k, Object v) {
                super(k);
                value = v;
            }
        }

该Map Hash碰撞后重新往下取index,而不是以链表形式存储

ThreadLocal.set

    public void set(T value) {
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null)
            map.set(this, value);
        else
            createMap(t, value);
    }

ThreadLocal.getMap(Thread t)

    ThreadLocalMap getMap(Thread t) {
        return t.threadLocals;
    }

指向Thread.threadLocals
map.set和createMap两个方法可以看到ThreadLocalMap的存储逻辑

ThreadLocal.createMap

    void createMap(Thread t, T firstValue) {
        t.threadLocals = new ThreadLocalMap(this, firstValue);
    }
    // ...
    ThreadLocalMap(ThreadLocal firstKey, Object firstValue) {
        table = new Entry[INITIAL_CAPACITY];
        int i = firstKey.threadLocalHashCode & (INITIAL_CAPACITY - 1);
        table[i] = new Entry(firstKey, firstValue);
        size = 1;
        setThreshold(INITIAL_CAPACITY);
    }
    

可以看到ThreadLocalMap通过Thread来获取(map为Thread的实例变量), ThreadLocal存储的值在Map中又是通过ThreadLocal对象作为Key来存储的.

以前错误的认为: 以为ThreadLocal的值是根据Thread的id作为key来存储的.

InheritableThreadLocal.java

public class InheritableThreadLocal extends ThreadLocal {
    /**
     * Computes the child's initial value for this inheritable thread-local
     * variable as a function of the parent's value at the time the child
     * thread is created.  This method is called from within the parent
     * thread before the child is started.
     * 

* This method merely returns its input argument, and should be overridden * if a different behavior is desired. * * @param parentValue the parent thread's value * @return the child thread's initial value */ protected T childValue(T parentValue) { return parentValue; } /** * Get the map associated with a ThreadLocal. * * @param t the current thread */ ThreadLocalMap getMap(Thread t) { return t.inheritableThreadLocals; } /** * Create the map associated with a ThreadLocal. * * @param t the current thread * @param firstValue value for the initial entry of the table. */ void createMap(Thread t, T firstValue) { t.inheritableThreadLocals = new ThreadLocalMap(this, firstValue); } }

他里面的方法都是对子类ThreadLocal的复写

InteritableThreadLocal的是对ThreadLocal的一种增强, 子线程可以继承父线程中的ThreadLocal存储对象
它通过一下步骤来实现

Thread.init

private void init(...,boolean inheritThreadLocals) {
    // ...
    Thread parent = currentThread();
    // ...
    if (inheritThreadLocals && parent.inheritableThreadLocals != null)
    this.inheritableThreadLocals =
        ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);
    // ...
}

ThreadLocal.createInheritedMap

    static ThreadLocalMap createInheritedMap(ThreadLocalMap parentMap) {
        return new ThreadLocalMap(parentMap);
    }
    
    // ...
    private ThreadLocalMap(ThreadLocalMap parentMap) {
        Entry[] parentTable = parentMap.table;
        int len = parentTable.length;
        setThreshold(len);
        table = new Entry[len];

        for (int j = 0; j < len; j++) {
            Entry e = parentTable[j];
            if (e != null) {
                @SuppressWarnings("unchecked")
                ThreadLocal key = (ThreadLocal) e.get();
                if (key != null) {
                    Object value = key.childValue(e.value);
                    Entry c = new Entry(key, value);
                    int h = key.threadLocalHashCode & (len - 1);
                    while (table[h] != null)
                        h = nextIndex(h, len);
                    table[h] = c;
                    size++;
                }
            }
        }
    }
 
 

ThreadLocalMap从parentMap中将数据拷贝到当前线程的ThreadLocalMap对象中,通过key.childValue(e.value)该方法在InheritableThreadLocal中有出现,就是直接引用该值对象(浅拷贝)

你可能感兴趣的:(ThreadLocal和InheriableThreadLocal)