目錄
前面講Jdbc連接時涉及到ThreadLocal的內容由於要解釋的東西太多,所以另開一篇解釋
ThreadLocal裏面的幾個方法
1、set(T value) 設置ThreadLocal中當前線程共享變量的值。
2、get() 獲取ThreadLocal中當前線程共享變量的值。
3、remove()移除ThreadLocal中當前線程共享變量的值
set(T value)源碼:
public void set(T value) {
//獲取當前線程
Thread t = Thread.currentThread();
//在ThreadLocal 中,以t來獲取當前線程的一個ThreadLocalMap
ThreadLocalMap map = getMap(t);
//如果ThreadLocal中有這個map,就把當前類和對應的值傳進去
if (map != null)
map.set(this, value);
//如果沒有這個map,就新建一個t線程的ThreadLocalMap,並將value值傳進去
else
createMap(t, value);
}
//在創建t線程的ThreadLocalMap時,同樣要把當前類作爲Key值傳入此ThreadLocalMap中
void createMap(Thread t, T firstValue) {
t.threadLocals = new ThreadLocalMap(this, firstValue);
}
get()源碼:
public T get() {
//獲取當前線程
Thread t = Thread.currentThread();
//獲取當前線程的map
ThreadLocalMap map = getMap(t);
//判斷當前線程的map是否存在,不爲空
if (map != null) {
//如果存在,就獲取當前對象的Entry鍵值對
ThreadLocalMap.Entry e = map.getEntry(this);
//判斷這個鍵值對是否爲空
if (e != null) {
//如果不是空,就返回對應的value值
@SuppressWarnings("unchecked")
T result = (T)e.value;
return result;
}
}
//此處是當前線程的map不存在,返回setInitialValue,進程初始化
return setInitialValue();
}
private T setInitialValue() {
//調用initialValue方法,此方法是初始化ThreadLocal的方法,
T value = initialValue();
//下面一段代碼是再次判斷ThreadLocal中是否有當前線程的map
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
//根據初始化的內容,決定是在map中插入值,還是新建map插入值
if (map != null)
map.set(this, value);
else
createMap(t, value);
return value;
}
//初始化ThreadLocal的方法,一般會在創建ThreadLocal對象時重寫該方法,確保初始化時,不至於爲null
protected T initialValue() {
return null;
}
remove()源碼:
public void remove() {
ThreadLocalMap m = getMap(Thread.currentThread());
if (m != null)
m.remove(this);
}
移除當前線程的map
PS
1、ThreadLocalMap 是ThreadLocal裏面的一個內部類,相當於Map,是個雙列集合,但是是以(T t,ThreadLocalMap())的形式存儲數據的,ThreadLocalMap()是內部類ThreadLocalMap內的構造方法。
2、爲了防止內存溢出,在每條線程任務執行完後,要調用remove方法溢出ThreadLocal中的連接
3、ThreadLocalMap是根據線性探測的方法來插入數據的。所謂線性探測,就是根據初始key的hashcode值確定元素在table數組中的位置,如果發現這個位置上已經有其他key值的元素被佔用,則利用固定的算法尋找一定步長的下個位置,依次判斷,直至找到能夠存放的位置。ThreadLocalMap解決Hash衝突的方法就是利用步長加1或者減1,來尋找下一個相鄰的位置,直至找到合適的位置
4、因爲ThreadLocalMap處理hash衝突的複雜性,爲了提高性能,建議每個線程只存放一個變量。樣的話所有的線程存放到map中的Key都是相同的ThreadLocal,如果一個線程要保存多個變量,就需要創建多個ThreadLocal,多個ThreadLocal放入Map中時會極大的增加Hash衝突的可能。
tips:下面將我讀到的一篇關於ThreadLocal寫的不錯的文章連接附上,方便查閱。
總結
ThreadLocal通過給不同的線程分配各自特有的map,來區分不同的線程,並在每個map中存入以當前對象爲key,存儲數據爲value的Entry鍵值對來區分不同線程的任務,確保,當前線程只能處理當前線程的數據,不能處理其他線程的數據。
能力尚淺,有待進步,如有不足,不吝賜教!