美文网首页
线程学习->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