set過程
1、ThreadLocal.set(T value)方法
/**
* 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);
else
createMap(t, value);
}
當調用set值方法時,首先從當前線程獲取ThreadLocalMap對象map,判斷map是否爲空,不爲空則直接set值(key爲threadlocal對象),爲空則調用createMap方法。
2、ThreadLocalMap map = getMap(t)中的getMap(t)源碼。
/**
* 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;
}
3、t.threadLocals;的源碼
public
class Thread implements Runnable {
....
....
/* ThreadLocal values pertaining to this thread. This map is maintained
* by the ThreadLocal class. */
ThreadLocal.ThreadLocalMap threadLocals = null;
}
返回當前線程的ThreadLocalMap對象(默認爲null),ThreadLocalMap爲ThreadLocal的靜態內部類,由ThreadLocalMap中的enty對象存儲value值。
4、createMap()方法
/**
* 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
*/
void createMap(Thread t, T firstValue) {
t.threadLocals = new ThreadLocalMap(this, firstValue);
}
createMap方法時創建一個新的ThreadLocalMap並向這個新的ThreadLocalMap中存儲數據。
5、new ThreadLocalMap(this,firstValue)方法
/**
* Construct a new map initially containing (firstKey, firstValue).
* ThreadLocalMaps are constructed lazily, so we only create
* one when we have at least one entry to put in it.
*/
ThreadLocalMap(ThreadLocal<?> firstKey, Object firstValue) {
table = new Entry[INITIAL_CAPACITY];
int i = firstKey.threadLocalHashCode & (INITIAL_CAPACITY - 1);
table[i] = new Entry(firstKey, firstValue);
size = 1;
setThreshold(INITIAL_CAPACITY);
}
new一個Entry數組(默認大小爲INITIAL_CAPACITY = 16),並將this和value的值初始化到數組中。
get過程
/**
* 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);
if (map != null) {
ThreadLocalMap.Entry e = map.getEntry(this);
if (e != null) {
@SuppressWarnings("unchecked")
T result = (T)e.value;
return result;
}
}
return setInitialValue();
}
如果已經set了值,則返回,如果未set值則返回null。
ps:爲什麼不直接向Thread類中的ThreadLocalMap對象存取數據呢?
threadLocals默認是包級別訪問,所以不能直接從外部訪問該變量,只能同包下的類可以訪問threadlocals變量,而ThreadLocal和Thread恰好在同一個包中。
InheritableThreadLocal的使用