美文网首页
线程学习->10ThreadLocal

线程学习->10ThreadLocal

作者: 冉桓彬 | 来源:发表于2018-06-13 10:28 被阅读15次

废话不多说, 直接上代码;

一、demo(以Looper为例):

public final class Looper {

    static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();

    public static @Nullable Looper myLooper() {
        return sThreadLocal.get();
    }

    private static void prepare(boolean quitAllowed) {
        if (sThreadLocal.get() != null) {
            throw new RuntimeException("Only one Looper may be created per thread");
        }
        sThreadLocal.set(new Looper(quitAllowed));
    }
}
  • Looper源码中将Looper与线程进行绑定, 从而实现Thread : Looper = 1 : 1的关系;

二、ThreadLocal.set:

2.1 ThreadLocal.set:
public class ThreadLocal<T> {
    public void set(T value) {
        /**
         * 获取当前线程;
         */
        Thread t = Thread.currentThread();
        /**
         * ThreadLocalMap为Thread的成员变量, 默认为null;
         */
        ThreadLocalMap map = getMap(t);    模块<2.2>
        if (map != null)
            /**
             * 1. 如果map存在, 也就是通过createMap对t.threadLocals进行了初始化;
             * 2. 通过对模块<2.3>的分析可知, ThreadLocalMap通过set方式将当前value与
             *    ThreadLocal进行绑定, 而我们通常都是将ThreadLocal设置为单例模式, 
             *    所以通常value都集中在ThreadLocalMap(key--index)对应的链表中;
             */
            map.set(this, value);     模块<2.3>
        else
            /**
             * 1. 如果map为空, 通过createMap方式初始化t.threadLocals;
             * 2. 在初始化t.threadLocals时将Thread, ThreadLocal, ThreadLocalMap进行绑定;
             */
            createMap(t, value);      模块<2.4>
    }
}
2.2 ThreadLocal.getMap:
public class ThreadLocal<T> {
    ThreadLocalMap getMap(Thread t) {
        return t.threadLocals;
    }
}

public class Thread implements Runnable {
    /**
     * Looper与线程进行绑定与该变量有关, 默认为null;
     */
    ThreadLocal.ThreadLocalMap threadLocals = null;
}
2.3 ThreadLocalMap.set:
public class ThreadLocalMap<T> {
    /**
     * 1. ThreadLocalMap内部维护了一个Entry数组, 每一个Entry[i]又对应一个链表结构;   
     * 2. 通过key查找到对应的索引index, 如果index存在, 则遍历链表查找对应的value, 
     *    如果存在, 则替换, 不存在则通过new方式新增;        
     */
    private void set(ThreadLocal<?> key, Object value) {

        Entry[] tab = table;
        int len = tab.length;
        int i = key.threadLocalHashCode & (len-1);

        for (Entry e = tab[i]; e != null; e = tab[i = nextIndex(i, len)]) {
            ThreadLocalMap<?> k = e.get();
            if (k == key) {
                e.value = value;
                return;
            }
            if (k == null) {
                replaceStaleEntry(key, value, i);
                return;
            }
        }

        tab[i] = new Entry(key, value);
        int sz = ++size;
        if (!cleanSomeSlots(i, sz) && sz >= threshold)
            rehash();
}
2.4 ThreadLocalMap.createMap:
public class ThreadLocal<T> {
    /**
     * 结合模块<2.2> 可知, Thread : ThreadLocalMap : ThreadLocal = 1:1:1;
     */
    void createMap(Thread t, T firstValue) {
        t.threadLocals = new ThreadLocalMap(this, firstValue);
    }


    static class ThreadLocalMap {
        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);
        }
    }
}

四、ThreadLocal.get:

4.1 ThreadLocal.get:
public class ThreadLocal<T> {
    public T get() {
        Thread t = Thread.currentThread();
        /**
         * 或者当前线程的成员变量threadLocals;
         */
        ThreadLocalMap map = getMap(t);
        if (map != null) {
            /**
             * 通过ThreadLocal对应的key值算出对应的索引值index, 然后变量index
             * 对应的链表, 直至匹配到对应的value;
             */
            ThreadLocalMap.Entry e = map.getEntry(this);
            if (e != null) {
                @SuppressWarnings("unchecked")
                T result = (T)e.value;
                return result;
            }
        }
        /**
         * 如果不存在对应的value, 则先构造一个key-value(null), 然后再返回该value;
         */
        return setInitialValue();
    }
}

相关文章

网友评论

      本文标题:线程学习->10ThreadLocal

      本文链接:https://www.haomeiwen.com/subject/imgdeftx.html