java.lang.ThreadLocal<T>,java.lang.InheritableThreadLocal<T>
*概述
---以ThreadLocal为key,实现将对象(视为value)存储在当前线程的ThreadLocalMap中,那么就不存在线程间共享信息导致的并发问题.
主要用途
1)设计线程安全的类
2)存储无需共享的线程信息
---并发中是否使用ThreadLocal,关键问题在于ThreadLocal的性能是否满足要求,性能问题主要出在实现代码中的Thread.currentThread(),
看了些文章,在jdk1.4之后,ThreadLcoal的实现得到优化,对于性能问题如何留待验证.
*源码分析
---设计思路
---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定制复制的行为.
源码如下
//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); //重定向到线程的对应位置 } }
*参考
http://en.wikipedia.org/wiki/Thread-local_storage
http://www.javaworld.com/javaworld/jw-11-2001/jw-1116-dcl.html
http://www.ibm.com/developerworks/java/library/j-threads3/index.html(推荐阅读)