zoukankan      html  css  js  c++  java
  • ThreadLocal源码解析

    主要用途

      1)设计线程安全的类

      2)存储无需共享的线程信息

    设计思路

    ThreadLocalMap原理

    1)对象存储位置-->当前线程的ThreadLocalMap

      ThreadLocalMap是在ThreadLocal中定义的静态内部类,用于存放线程的信息,以ThreadLocal或InheritableThreadLocal为key,对象为value.每个Thread都有两个ThreadLocalMap,如下

        /* ThreadLocal values pertaining to this thread. This map is maintained
         * by the ThreadLocal class. */
       //存放线程自己的信息,注册ThreadLocal
        ThreadLocal.ThreadLocalMap threadLocals = null;
    
        /*
         * InheritableThreadLocal values pertaining to this thread. This map is
         * maintained by the InheritableThreadLocal class.  
         */ 
         //父线程信息的拷贝,注册InheritableThreadLocal
        ThreadLocal.ThreadLocalMap inheritableThreadLocals = null;

      2)ThreadLocalMap,实现自定义Map,实现存储的大致原理如下

            /**
             * 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.
             */
         //封装ThreadLocal和对象
            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.
             */
         //数组存放entry
            private Entry[] table;
            private Entry getEntry(ThreadLocal key) {
            //利用ThreadLocal的哈希值属性定位在table中的位置
                int i = key.threadLocalHashCode & (table.length - 1);
                Entry e = table[i];
                if (e != null && e.get() == key)
                    return e;
                else
                    return getEntryAfterMiss(key, i, e);
            }

    ThreadLocal原理

        /**
         * Returns the value in the current thread's copy of this
         * thread-local variable.  If the variable has no value for the
         * current thread, it is first initialized to the value returned
         * by an invocation of the {@link #initialValue} method.
         *
         * @return the current thread's value of this thread-local
         */
        public T get() {
            Thread t = Thread.currentThread();
            ThreadLocalMap map = getMap(t); //获取当前线程的ThreadLocalMap
            if (map != null) {
                ThreadLocalMap.Entry e = map.getEntry(this);
                if (e != null)
                    return (T)e.value;
            }
            return setInitialValue();
        }
        /**
         * Sets the current thread's copy of this thread-local variable
         * to the specified value.  Most subclasses will have no need to 
         * override this method, relying solely on the {@link #initialValue}
         * method to set the values of thread-locals.
         *
         * @param value the value to be stored in the current thread's copy of
         *        this thread-local.
         */
        public void set(T value) {
            Thread t = Thread.currentThread();
            ThreadLocalMap map = getMap(t);
            if (map != null)
                map.set(this, value); //key=ThreadLocal,value=对象
            else
                createMap(t, value);
        }
        /**
         * Get the map associated with a ThreadLocal. Overridden in
         * InheritableThreadLocal.
         *
         * @param  t the current thread
         * @return the map
         */
        ThreadLocalMap getMap(Thread t) {
            return t.threadLocals; //获取当前线程的ThreadLocalMap
        }
        protected T initialValue() { //初始化ThreadLocal时,预定义初始化value,默认为null
            return null;
        }
        /**
         * Variant of set() to establish initialValue. Used instead
         * of set() in case user has overridden the set() method.
         *
         * @return the initial value
         */
        private T setInitialValue() {
            T value = initialValue(); //获取ThreadLocal初始化的value
            Thread t = Thread.currentThread();
            ThreadLocalMap map = getMap(t);
            if (map != null)
                map.set(this, value);
            else
                createMap(t, value);
            return value;
        }
        /**
         * Create the map associated with a ThreadLocal. Overridden in
         * InheritableThreadLocal.
         *
         * @param t the current thread
         * @param firstValue value for the initial entry of the map
         * @param map the map to store.
         */
        void createMap(Thread t, T firstValue) {
            t.threadLocals = new ThreadLocalMap(this, firstValue); //定义当前线程的 ThreadLocal.ThreadLocalMap threadLocals
        }

      注意,在new ThreadLocal时可以通过T java.lang.ThreadLocal.initialValue()定义存储的初始化对象

    InheritableThreadLocal原理

      主要实现

      1)覆盖ThreadLocal的方法,将存储位置定位到ThreadLocal.ThreadLocalMap inheritableThreadLocals

      2)在从父线程获取inheritableThreadLocals,通过childValue定制复制的行为.

      源码如下

    public class InheritableThreadLocal<T> extends ThreadLocal<T> { //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.
         * <p>
         * 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;   //在ThreadLocalMap(ThreadLocalMap parentMap)时,定制复制行为
        }
        /**
         * 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.
         * @param map the map to store.
         */
        void createMap(Thread t, T firstValue) {
            t.inheritableThreadLocals = new ThreadLocalMap(this, firstValue);   //重定向到线程的对应位置
        }
    }
  • 相关阅读:
    75. Sort Colors
    101. Symmetric Tree
    121. Best Time to Buy and Sell Stock
    136. Single Number
    104. Maximum Depth of Binary Tree
    70. Climbing Stairs
    64. Minimum Path Sum
    62. Unique Paths
    css知识点3
    css知识点2
  • 原文地址:https://www.cnblogs.com/wxgblogs/p/5501050.html
Copyright © 2011-2022 走看看