美文网首页
ThreadLocal的源码解析

ThreadLocal的源码解析

作者: Okami_ | 来源:发表于2021-09-10 18:28 被阅读0次
    java.lang.ThreadLocal

    存数据

    1、获取当前线程持有的threadLocalMap对象
    2、如果map对象不为空,则set值,key为threadLocal对象本身,value为set的值
    3、如果map对象为null,则创建map对象并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);
        }
    

    map对象为当前线程维护的ThreadLocalMap对象

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

    如果是第一次set值,则new一个新的ThreadLocalMap对象并赋值,然后交给当前线程维护

        void createMap(Thread t, T firstValue) {
            t.threadLocals = new ThreadLocalMap(this, firstValue);
        }
    
    

    Thread类中维护了一个ThreadLocalMap对象

    • java.lang.Thread
        /* ThreadLocal values pertaining to this thread. This map is maintained
         * by the ThreadLocal class. */
        ThreadLocal.ThreadLocalMap threadLocals = null;
    
    • java.lang.ThreadLocal.ThreadLocalMap
        static class ThreadLocalMap {
            static class Entry extends WeakReference<ThreadLocal<?>> {
                /** The value associated with this ThreadLocal. */
                Object value;
    
                Entry(ThreadLocal<?> k, Object v) {
                    super(k);
                    value = v;
                }
            }
    
            /**
             * The table, resized as necessary.
             * table.length MUST always be a power of two.
             */
            private Entry[] table;
        }
    
           private void set(ThreadLocal<?> key, Object value) {
    
                // We don't use a fast path as with get() because it is at
                // least as common to use set() to create new entries as
                // it is to replace existing ones, in which case, a fast
                // path would fail more often than not.
    
                Entry[] tab = table;
                int len = tab.length;
                // 对key的hash与table.length取模,获取entry在数组中存储的位置
                int i = key.threadLocalHashCode & (len-1);
    
                for (Entry e = tab[i];
                     e != null;
                     e = tab[i = nextIndex(i, len)]) {
                    ThreadLocal<?> 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();
            }
    
           /**
             * Increment i modulo len.
             */
            private static int nextIndex(int i, int len) {
                return ((i + 1 < len) ? i + 1 : 0);
            }
    

    取数据

    1、获取当前线程维护的threadLocalMap
    2、从map中获取Entry,key值为threadLocal本身
    3、返回entry中的value值

        public T get() {
            Thread t = Thread.currentThread();
            ThreadLocalMap map = getMap(t);
            if (map != null) {
                ThreadLocalMap.Entry e = map.getEntry(this);
                if (e != null) {
                    @SuppressWarnings("unchecked")
                    T result = (T)e.value;
                    return result;
                }
            }
            return setInitialValue();
        }
    

    相关文章

      网友评论

          本文标题:ThreadLocal的源码解析

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