java.lang.ThreadLocal<T>,java.lang.InheritableThreadLocal<T> *概述 ---以ThreadLocal为key,实现将对象(视为value)存...
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,如下
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,实现存储的大致原理如下
ThreadLocalMap源码 /**
* 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原理
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定制复制的行为.
源码如下
InheritableThreadLocal源码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); //重定向到线程的对应位置
}
}
*参考
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(推荐阅读)
http://java.dzone.com/articles/java-thread-local-%E2%80%93-how-use?utm_source=feedburner&utm_medium=feed&utm_campaign=Feed:+javalobby/frontpage+%28Javalobby+/+Java+Zone%29