思考:對ThreadLocal的理解多少?
springboot葵花寶典
主要分享JAVA技術,主要包含SpringBoot、SpingCloud、Docker、中間件等技術,以及Github開源項目
ThreadLocal是多線程中對于解決線程安全的一個操作類,它會為每個線程都分配一個獨立的線程副本從而解決了變量并發訪問沖突的問題。ThreadLocal 同時實現了線程內的資源共享
案例:使用JDBC操作數據庫時,會將每一個線程的Connection放入各自的ThreadLocal中,從而保證每個線程都在各自的 Connection 上進行數據庫的操作,避免A線程關閉了B線程的連接。
圖片
ThreadLocal本質來說就是一個線程內部存儲類,從而讓多個線程只操作自己內部的值,從而實現線程數據隔離
每個線程內有一個 ThreadLocalMap 類型的成員變量,用來存儲資源對象
圖片
ThreadLocalMap 的一些特點
key 的 hash 值統一分配
初始容量 16,擴容因子 2/3,擴容容量翻倍
key 索引沖突后用開放尋址法解決沖突
set(value) 設置值: 以 ThreadLocal 自己作為 key,資源對象作為 value,放入當前線程的 ThreadLocalMap 集合中
get() 獲取值: 以 ThreadLocal 自己作為 key,到當前線程中查找關聯的資源值
remove() 清除值: 以 ThreadLocal 自己作為 key,移除當前線程關聯的資源值
代碼案例
public class ThreadLocalTest { static ThreadLocal<String> threadLocal = new ThreadLocal<>(); public static void main(String[] args) { new Thread(() -> { String name = Thread.currentThread().getName(); threadLocal.set("zbbmeta"); print(name); System.out.println(name + "-after remove : " + threadLocal.get()); }, "t1").start(); new Thread(() -> { String name = Thread.currentThread().getName(); threadLocal.set("zbbmeta"); print(name); System.out.println(name + "-after remove : " + threadLocal.get()); }, "t2").start(); } static void print(String str) { //打印當前線程中本地內存中本地變量的值 System.out.println(str + " :" + threadLocal.get()); //清除本地內存中的本地變量 threadLocal.remove(); }}
在介紹內存泄露問題問題之前先介紹一下Java對象中的四種引用類型:Java對象中的四種引用類型:
Object obj = new Object();
Object obj = new Object();SoftReference<Object> softRef = new SoftReference<>(obj);
Object obj = new Object();WeakReference<Object> weakRef = new WeakReference<>(obj);
Object obj = new Object();PhantomReference<Object> phantomRef = new PhantomReference<>(obj, referenceQueue);
每一個Thread維護一個ThreadLocalMap,在ThreadLocalMap中的Entry對象繼承了WeakReference,其中key為使用弱引用的ThreadLocal實例,value為線程變量的副本
圖片
ThreadLocalMap 中的 key 被設計為弱引用,原因如下
Thread 可能需要長時間運行(如線程池中的線程),如果 key 不再使用,需要在內存不足(GC)時釋放其占用的內存
內存釋放時機
僅是讓 key 的內存釋放,關聯 value 的內存并不會釋放
面試官:談談你對ThreadLocal的理解
候選人:
ThreadLocal 主要功能有兩個:
- 第一個是可以實現資源對象的線程隔離,讓每個線程各用各的資源對象,避免爭用引發的線程安全問題
- 第二個是實現了線程內的資源共享
面試官:好的,那你知道ThreadLocal的底層原理實現嗎?
候選人:
在ThreadLocal內部維護了一個一個 ThreadLocalMap 類型的成員變量,用來存儲資源對象
當我們調用 set 方法,就是以 ThreadLocal 自己作為 key,資源對象作為 value,放入當前線程的 ThreadLocalMap 集合中
當調用 get 方法,就是以 ThreadLocal 自己作為 key,到當前線程中查找關聯的資源值
當調用 remove 方法,就是以 ThreadLocal 自己作為 key,移除當前線程關聯的資源值
面試官:好的,那關于ThreadLocal會導致內存溢出這個事情,了解嗎?
候選人:
是應為ThreadLocalMap 中的 key 被設計為弱引用,它是被動的被GC調用釋放key,不過關鍵的是只有key可以得到內存釋放,而value不會,因為value是一個強引用。
在使用ThreadLocal 時都把它作為靜態變量(即強引用),因此無法被動依靠 GC 回收,建議主動的remove 釋放 key,這樣就能避免內存溢出。
本文鏈接:http://www.www897cc.com/showinfo-26-34920-0.html談談你對ThreadLocal的理解
聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。郵件:2376512515@qq.com
上一篇: StarRocks在支付對賬領域的應用
下一篇: 大型直播活動保障S13的實踐和思考