前面我們分析了 thread類的原始碼,有了前面的鋪墊,通過原始碼 理解threadlocal的秘密就容易多了。
threadlocal類 提供了 get/set執行緒區域性變數的實現,threadlocal成員變數與正常的成員變數不同,每個執行緒都可以通過 threadlocal成員變數 get/set自己的專屬值。threadlocal例項 通常是類中的私有靜態變數,常用於將狀態與執行緒關聯,例如:使用者id或事務id。
public
class
threadlocal
threadlocalmap getmap
(thread t)
void
createmap
(thread t, t firstvalue)
public t get()
}return
setinitialvalue()
;}public
void
remove()
/** * 與大部分 map 的實現相同,底層也是使用 動態陣列來儲存 鍵值對entry,也有rehash、resize等
* 操作
*/static
class
threadlocalmap
}// 看過 hashmap 或 concurrenthashmap 原始碼的同學 一定下面對這些**很眼熟
/** * 陣列初始容量
*/private
static
final
int initial_capacity =16;
/** * entry陣列,用於儲存 k, object v>鍵值對
*/private entry[
] table;
/** * entry元素數量
*/private
int size =0;
/** * 類似於 hashmap 擴容因子機制
*/private
int threshold;
// default to 0
private
void
setthreshold
(int len)
private
static
intnextindex
(int i,
int len)
private
static
intprevindex
(int i,
int len)
/** * 系列構造方法
*/threadlocalmap
(threadlocal<
?> firstkey, object firstvalue)
private
threadlocalmap
(threadlocalmap parentmap)}}
}/**
* 根據 threadlocal物件 獲取其對應的 entry例項
*/private entry getentry
(threadlocal<
?> key)
/** * 常規map實現類 的set()方法,只不過這裡的 key被規定為 threadlocal型別
*/private
void
set(threadlocal<
?> key, object value)
// 如果key為null,用新key、value覆蓋,同時清理歷史key=null的陳舊資料
if(k == null)
} tab[i]
=new
entry
(key, value)
;int sz =
++size;
// 若超過閥值,則rehashif(
!cleansomeslots
(i, sz)
&& sz >= threshold)
rehash()
;}/** * remove the entry for key.
*/private
void
remove
(threadlocal<
?> key)}}
/** * 調整當前table的容量。首先掃瞄整個容器,以刪除過時的條目,如果這不能充分縮小表的大小,
* 將進行擴容操作
*/private
void
rehash()
/** * 擴容為原容量的兩倍
*/private
void
resize()
else}}
// 設定新的閾值
setthreshold
(newlen)
; size = count;
table = newtab;}}
}
簡單畫個圖總結一下 threadlocal 的原理,如下。
最後強調一下 threadlocal的使用注意事項:
threadlocal 不是用來解決執行緒安全問題的,多執行緒不共享,不存在競爭!其目的是使執行緒能夠使用本地變數。
專案如果使用了執行緒池,那麼執行緒**後threadlocal變數要remove掉,否則執行緒池**執行緒後,變數還在記憶體中,可能會帶來意想不到的後果!例如tomcat容器的執行緒池,可以在***中處理:繼承 handlerinterceptoradapter,然後複寫 aftercompletion()方法,remove掉變數!!!
ThreadLocal原始碼理解
threadlocal其實原理是建立了多份相同資料儲存在堆記憶體上,每個執行緒的thread類裡有threadlocal.threadlocalmap threadlocals的屬性來指向存位置,所以每個執行緒修改都不會影響到其他執行緒的資料 首先說下下面用到的東西 threadlocalmap為t...
ThreadLocal原始碼分析
在理解handler looper之前,先來說說threadlocal這個類,聽名字好像是乙個本地執行緒的意思,實際上它並不是乙個thread,而是提供乙個與執行緒有關的區域性變數功能,每個執行緒之間的資料互不影響。我們知道使用handler的時候,每個執行緒都需要有乙個looper物件,那麼and...
ThreadLocal 原始碼解讀
在正式讀 前先簡單介紹threadlocal的實現方式。每個執行緒都會有乙個threadlocalmap,只有在使用到threadlocal的時候才會初始化threadlocalmap。需要儲存的物件t會被放到entry裡面儲存在threadlocalmap的陣列中,entry是乙個鍵值對的資料結構...