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);   //重定向到线程的对应位置
        }
    }
  • 相关阅读:
    Ajax实现异步上传图片
    python文章的抓取
    python
    Python的MySQLdb模块安装
    import _mysql----ImportError: DLL load failed: %1 不是有效的 Win32 应用程序。
    安装第三方模块时遇到Python version 2.7 required, which was not found
    beautifulSoup安装
    安装setuptools和pip
    python 的简单抓取图片
    python
  • 原文地址:https://www.cnblogs.com/wxgblogs/p/5501050.html
Copyright © 2011-2022 走看看