原文:blog.csdn.net/qunqunstyle99/article/details/94717256
ThreadLocal是什么
ThreadLocal是一個本地執行緒副本變數工具類,主要用于將私有執行緒和該執行緒存放的副本物件做一個映射,各個執行緒之間的變數互不干擾,在高并發場景下,可以實作無狀態的呼叫,特別適用于各個執行緒依賴不通的變數值完成操作的場景,
下圖為ThreadLocal的內部結構圖

從上面的結構圖,我們已經窺見ThreadLocal的核心機制:
- 每個Thread執行緒內部都有一個Map,
- Map里面存盤執行緒本地物件(key)和執行緒的變數副本(value)
- 但是,Thread內部的Map是由ThreadLocal維護的,由ThreadLocal負責向map獲取和設定執行緒的變數值,
所以對于不同的執行緒,每次獲取副本值時,別的執行緒并不能獲取到當前執行緒的副本值,形成了副本的隔離,互不干擾,
推薦一個開源免費的 Spring Boot 最全教程:
https://github.com/javastacks/spring-boot-best-practice
ThreadLocalMap

ThreadLocalMap是ThreadLocal的內部類,沒有實作Map介面,用獨立的方式實作了Map的功能,其內部的Entry也獨立實作,
和HashMap的最大的不同在于,ThreadLocalMap結構非常簡單,沒有next參考,也就是說ThreadLocalMap中解決Hash沖突的方式并非鏈表的方式,而是采用線性探測的方式,(ThreadLocalMap如何解決沖突?)
在ThreadLocalMap中,也是用Entry來保存K-V結構資料的,但是Entry中key只能是ThreadLocal物件,這點被Entry的構造方法已經限定死了,
static class Entry extends WeakReference<ThreadLocal> {
/** The value associated with this ThreadLocal. */
Object value;
Entry(ThreadLocal k, Object v) {
super(k);
value = https://www.cnblogs.com/javastack/archive/2023/03/22/v;
}
}
注意了!!
Entry繼承自WeakReference(弱參考,生命周期只能存活到下次GC前),但只有Key是弱參考型別的,Value并非弱參考,(問題馬上就來了)
由于ThreadLocalMap的key是弱參考,而Value是強參考,這就導致了一個問題,ThreadLocal在沒有外部物件強參考時,發生GC時弱參考Key會被回收,而Value不會回收,
當執行緒沒有結束,但是ThreadLocal已經被回收,則可能導致執行緒中存在ThreadLocalMap<null, Object>的鍵值對,造成記憶體泄露,(ThreadLocal被回收,ThreadLocal關聯的執行緒共享變數還存在),
如何避免泄漏
為了防止此類情況的出現,我們有兩種手段,
1、使用完執行緒共享變數后,顯示呼叫ThreadLocalMap.remove方法清除執行緒共享變數;
既然Key是弱參考,那么我們要做的事,就是在呼叫ThreadLocal的get()、set()方法時完成后再呼叫remove方法,將Entry節點和Map的參考關系移除,這樣整個Entry物件在GC Roots分析后就變成不可達了,下次GC的時候就可以被回收,
2、JDK建議ThreadLocal定義為private static,這樣ThreadLocal的弱參考問題則不存在了,
文章參考:
-
www.jianshu.com/p/98b68c97df9b
-
www.cnblogs.com/coshaho/p/5127135.html
近期熱文推薦:
1.1,000+ 道 Java面試題及答案整理(2022最新版)
2.勁爆!Java 協程要來了,,,
3.Spring Boot 2.x 教程,太全了!
4.別再寫滿屏的爆爆爆炸類了,試試裝飾器模式,這才是優雅的方式!!
5.《Java開發手冊(嵩山版)》最新發布,速速下載!
覺得不錯,別忘了隨手點贊+轉發哦!
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/547777.html
標籤:其他
