7、ThreadLocal底層實現
每個Thread都有一個ThreadLocalMap物件,ThreadLocalMap持有物件的引用,
該物件跟當前執行緒繫結,ThreadLocalMap以當前的threadLocal物件為key,
以ThreadLocal裡面存的值為value。儲存一份變數的副本,副本儲存線上程中的,
而不是儲存在ThreadLocal變數中;從而實現執行緒之間的資料的隔離
複製程式碼
8、 ThreadLocal原始碼:
1)、set()方法:
public void set(T value) {
//獲取當前執行緒物件
Thread t = Thread.currentThread();
//獲取當前執行緒物件的ThreadLocalMap
ThreadLocalMap map = getMap(t);
if (map != null)
//以當前threadLocal物件為key,實際儲存物件為value
map.set(this, value);
else
createMap(t, value);
}
//獲取Thread類中的ThreadLocalMap物件
ThreadLocalMap getMap(Thread t) {
return t.threadLocals;
}
//建立Thread類中的ThreadLocalMap成員物件
void createMap(Thread t, T firstValue) {
t.threadLocals = new ThreadLocalMap(this, firstValue);
}
//初始化ThreadLocalMap物件
ThreadLocalMap(ThreadLocal<?> firstKey, Object firstValue) {
//INITIAL_CAPACITY初始值為16
table = new Entry[INITIAL_CAPACITY];
int i = firstKey.threadLocalHashCode & (INITIAL_CAPACITY - 1);
table[i] = new Entry(firstKey, firstValue);
size = 1;
setThreshold(INITIAL_CAPACITY);
}
//初始化載入因子
private void setThreshold(int len) {
threshold = len * 2 / 3;
}
2)、get()方法:
public T get() {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null) {
//threadlocal例項為key獲取到對應Entry,然後從Entry中取出物件
ThreadLocalMap.Entry e = map.getEntry(this);
if (e != null) {
@SuppressWarnings("unchecked")
T result = (T)e.value;
return result;
}
}
//map為空時,設定初始值
return setInitialValue();
}
private T setInitialValue() {
T value = initialValue();
//同set方法一樣
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null)
map.set(this, value);
else
createMap(t, value);
return value;
}
protected T initialValue() {
return null;
}
3)、remove()方法:
public void remove() {
ThreadLocalMap m = getMap(Thread.currentThread());
if (m != null)
m.remove(this);
}
複製程式碼
9、ThreadLocal使用場景(JDBC的連線、管理會話HttpSession等)
如圖: