线程变量,每一个线程中都维护了一个ThreadLocalMap对象,用于存放该线程中的ThreadLocal->Object类型的数据。
我们在ThreadLocal中设置的值都是直接和线程相关联的,不存在线程安全问题。
但是每个线程中都维护一个map会极大消耗内存,所以这是一个
以空间换时间
的策略
源代码解析
构造函数什么都没有做,所以看set()
ThreadLocal.class
/**
* Creates a thread local variable.
*/
public ThreadLocal() {
}
在set方法中初始化
ThreadLocal.class
/**
* 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对象
ThreadLocalMap map = getMap(t);
if (map != null) // 若已经初始化map,即不是第一次
// 将当前 ThreadLocal对象为key,任意对象为值存入map
map.set(this, value);
else // 如果没有初始化map,即第一次
//实例化ThreadLocalMap,将value添加到map
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;
}
/**
* 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);
}
//get()
ThreadLocal.class
/**
* 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); //获取当前线程中的map
if (map != null) {
ThreadLocalMap.Entry e = map.getEntry(this); //根据ThreadLocal获取entry对象
if (e != null)
return (T)e.value;
}
return setInitialValue();
}
/**
* 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(); //null
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t); //获取当前线程中的ThreadLocalMap对象
if (map != null)
map.set(this, value); //将null添加到map
else
createMap(t, value); //初始化map,将null添加进map
return value;
}
protected T initialValue() {
return null;
}
// 线程之中存在一个 ThreadLocalMap 的对象
Thread.class
/* ThreadLocal values pertaining to this thread. This map is maintained
* by the ThreadLocal class. */
ThreadLocal.ThreadLocalMap threadLocals = null;
/*
* InheritableThreadLocal values pertaining to this thread. This map is
* maintained by the InheritableThreadLocal class.
*/
ThreadLocal.ThreadLocalMap inheritableThreadLocals = null;
网友评论