文章目錄
- 1、作用
- 2、保存步驟
- 3、原理 / 記憶體泄漏
- 3.1 資料結構
- 3.2 設計原理
- 3.3 value如何清理
- 3.4 總結
- 4、四種參考型別
- 5、微信關注『方糖演算法』
1、作用
- ThreadLocal 在多執行緒環境中,
安全的保存執行緒本地變數,同一執行緒在某地保存資料,任意地方均可獲取, - 同一個ThreadLocal ,由于每個執行緒都有自己的 ThreadLocalMap ,所以
不同執行緒中保存的資料互不影響,
2、保存步驟

- 每個執行緒中都有一個 ThreadLocalMap 變數
threadLocal來保存 ThreadLocal 中的資料, - 在
threadLocals.set()中,先通過Thread.currentThread()獲取當前執行緒, - 通過
getMap(Thread t)獲取當前執行緒的ThreadLocalMap物件, - 當前的
threadLocal作為 key,保存的資料作為 value,構造一個Entry物件保存在ThreadLocalMap 中, - 呼叫
threadLocal.get()取資料也是先獲取到當前執行緒,以 threadLocal 為 key 從這個 ThreadLocalMap 中取出資料,
3、原理 / 記憶體泄漏
3.1 資料結構
- ThreadLocal 保存一個 value 時,會構造一個 Entry 插入到 ThreadLocalMap 中,
- Entry 繼承
弱參考類,key 指向 ThreadLocal 的弱參考,value 是強參考,
3.2 設計原理
對于一個 ThreadLocal 物件,通常會有兩個參考指向它:
- ①執行緒中宣告的
threadLocal變數,強參考 - ②執行緒底層 ThreadLocalMap 中鍵值對的
key,弱參考 - 不需要使用 ThreadLocal 物件時,將變數 threadLocal 置空,讓GC回收 ThreadLocal 物件
- 但是 key 也參考了 ThreadLocal 物件,這個 key 如果是強參考,ThreadLocal 物件就永遠不會被回收,但這里設計為弱參考,所以GC 發現 ThreadLocal 物件就會回收它,
- 但是 ThreadLocalMap 中的
value是強參考,value 中的物件不會回收,造成記憶體泄漏, - 最佳方法:使用完 ThreadLocal 物件后,主動呼叫
remove()方法,清理物件,
3.3 value如何清理
key 是弱參考,當不存在外部強參考時,會被自動回收,而 value 是強參考,參考鏈如下
Thread -> ThreadLocal -> Entry -> value
所以只有當 Thread 被回收,value 才會被回收,否則 value 將一直存在,但是讓每個執行緒關閉,是不現實的,在執行緒池中,大部分執行緒會伴隨著系統的整個周期,那么 value 可能會造成泄漏,
解決方法,在 ThreadLocalMap 進行set(),get(),remove()的時候,都進行清理:
private Entry getEntry(ThreadLocal<?> key) {
int i = key.threadLocalHashCode & (table.length - 1);
Entry e = table[i];
if (e != null && e.get() == key)
//如果找到key,直接回傳
return e;
else
//如果找不到,就會嘗試清理(說明key不在了,也就是threadLocal = null)
//換句話說,這個資料用不上了
return getEntryAfterMiss(key, i, e);
}
private Entry getEntryAfterMiss(ThreadLocal<?> key, int i, Entry e) {
Entry[] tab = table;
int len = tab.length;
while (e != null) {
// 整個e是entry ,也就是一個弱參考
ThreadLocal<?> k = e.get();
//如果找到了,就回傳
if (k == key)
return e;
if (k == null)
//如果key為null,說明弱參考已經被回收了
//那么就要在這里回收里面的value了
expungeStaleEntry(i);
else
//如果key不是要找的那個,那說明有hash沖突,這里是處理沖突,找下一個entry
i = nextIndex(i, len);
e = tab[i];
}
return null;
}
真正回收 value 的是 expungeStaleEntry()方法,在 remove 和 set 方法中都會呼叫這個方法,
ThreadLocal 為了避免記憶體泄露,不僅使用了弱參考維護 key ,還在每個操作上檢查 key 是否被回收,進而再回收value,
3.4 總結
- ThreadLocal 可能發生記憶體泄漏,
- 如果一直沒機會呼叫,set get remove 方法,記憶體泄漏依舊會發生,
- 所以養成良好的習慣,用完 ThreadLocal 變數 就主動 remove 它,
4、四種參考型別
1、強參考
- Object obj = new Object(),除非顯示將 obj 置空,否則GC不會回收,
- 應用場景:物件一般狀態,
2、軟參考
- 記憶體充足,不回收;只有記憶體不足,再回收,
SoftReference<String> softReference = new SoftReference<String>(str); - 應用場景:物件快取,
3、弱參考
- 比軟參考更弱,被GC掃描到直接回收,
- 應用場景:物件快取,
4、虛參考
- 虛參考不會決定物件的生命周期,如果一個物件只有虛參考,那么和沒參考一樣,隨時被回收,
- 應用場景:用來跟蹤物件被GC回收的活動
5、微信關注『方糖演算法』
各類面試資料、內推資源,關注微信公眾號獲取哦,

轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/320998.html
標籤:其他
上一篇:API介面安全性設計
