欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java中的線程ThreadLocal詳細(xì)解析

 更新時間:2023年10月26日 09:04:32   作者:buzhbuzh  
這篇文章主要介紹了Java中的線程ThreadLocal詳細(xì)解析,ThreadLocal是線程本地變量,存儲在ThreadLocal里面的數(shù)據(jù)都是線程安全的,一般ThreadLocal適用的場景多是各個線程間沒有變量共享需要的同步問題場景,需要的朋友可以參考下

一 Java中的引用關(guān)系

Java中的引用分為了強(qiáng)引用、弱引用、軟引用、虛引用

  • 強(qiáng)引用: 垃圾回收的時候,如果內(nèi)存不足也不會進(jìn)行垃圾回收,會報out-of-memory異常
  • 弱引用: 垃圾回收的時候,如果內(nèi)存不夠,則數(shù)據(jù)被回收.
  • 軟引用: 垃圾回收的時候,軟引用會立刻進(jìn)行回收
  • 虛引用: 垃圾回收的時候,軟引用會立刻進(jìn)行回收

二 ThreadLocal代碼實(shí)現(xiàn)

ThreadLocal是線程本地變量,存儲在ThreadLocal里面的數(shù)據(jù)都是 線程安全的.

一般ThreadLocal適用的場景多是各個線程間沒有變量共享需要的同步問題場景,比如一個簡單的SimpleDateFormat類,該類不是線程安全的,卻是有狀態(tài)的,如果將SimpleDateFormat設(shè)置為靜態(tài)的,所有線程共享,那么就會出現(xiàn)線程安全的問題,其中一個線程修改日期格式為“yyyyMMdd”,然后可能會影響到另外一個需要格式為“yyyy-MM-dd”的線程。但是如果在方法中每次用到的時候都new一個SimpleDateFormat類又太費(fèi)內(nèi)存(SimpleDateFormat這種簡單的類倒還好,若是一些比較占用資源的比如數(shù)據(jù)庫連接類等,就會讓加大整個數(shù)據(jù)庫的壓力),這時候采用ThreadLocal為每一個線程保存一份SimpleDateFormat副本,這樣既不會說每次調(diào)用方法都會生成一個對象,也不會在并發(fā)時產(chǎn)生線程同步問題。這就像是在共享一個靜態(tài)變量和每次使用都new一個對象兩者之間的一種折中處理方法。

自己實(shí)現(xiàn)的ThreadLocal

在這里插入圖片描述

通過一個全局map, key是Thread對象,value是對應(yīng)存儲的數(shù)據(jù),這種情況下 如果map不銷毀,對應(yīng)的Thread線程就不發(fā)被回收,導(dǎo)致內(nèi)存泄露

JDK中使用的ThreadLocal

在這里插入圖片描述

JDK8中在Thread對象中引用ThreadLocalMap,ThreadLocalMap的生命周期是Thread是同一個生命周期.

ThreadLocalMap的實(shí)現(xiàn)

(1) Entry數(shù)組實(shí)現(xiàn)

在這里插入圖片描述

Entry數(shù)組是線程中實(shí)際存放數(shù)據(jù)的地方,key是ThreadLocal,是一個弱引用,value是對應(yīng)存儲的值.

為什么ThreadLocalMap#key是一個弱引用

如果外部不使用了ThreadLocal,則對應(yīng)的數(shù)據(jù)不應(yīng)該存儲在ThreadLocal中,應(yīng)該被刪除掉,防止內(nèi)存泄漏

ThreadLocalMap的屬性

        private static final int INITIAL_CAPACITY = 16;
    	//存儲數(shù)據(jù)的地方
        private Entry[] table; //
    	//數(shù)量
        private int size = 0;
        private int threshold; // Default to 0

ThreadLocal的方法

ThreadLocal#set()方法

在這里插數(shù)據(jù)入圖片描述

(1) 第一步 獲取到當(dāng)前線程的ThreadLocalMap

(2) 第二步 初始化ThreadLocalMap

(3) 第三步 將ThreadLocal作為key,value值作為值,設(shè)置到map中

ThreadLocal # get()方法

在這里插入圖片描述

方法主要完成兩個功能: (1) 完成數(shù)據(jù)的讀取 (2) 將ThreadLocalMap中key為NULL的數(shù)據(jù)從ThreadLocalMap中刪除

ThreadLocalMap中的entry其實(shí)是繼承的弱引用,如果該弱引用指向的ThreadLocal沒有在外部被強(qiáng)引用指向的話,在下次gc的時候就會被回收,那這樣的話就會出現(xiàn)ThreadLocalMap中存在key為null的情況,這樣的數(shù)據(jù)對于map來講是臟數(shù)據(jù),這樣的臟數(shù)據(jù)沒有用,卻一直占用著map的存儲空間,這其實(shí)就是一種內(nèi)存泄漏,所以需要來釋放掉這些空間

三 ThreadLocalMap的內(nèi)存泄漏問題

如果ThreadLocal無強(qiáng)引用進(jìn)行應(yīng)用,則在垃圾回收的時候會把這個key進(jìn)行回收.

這個時候,因?yàn)榫€程還存活,所以ThreadLocalMap依舊存在,但是key為null,這個 key對應(yīng)的value就無法被訪問到了,造成內(nèi)存泄漏.

JDK團(tuán)隊(duì)自己的解決辦法

調(diào)用get()、set()方法的時候,自動清理掉ThreadLocalMap中key為null的數(shù)據(jù)

開發(fā)者的解決辦法 使用ThreadLocal后,調(diào)用ThreadLocal

到此這篇關(guān)于Java中的線程ThreadLocal詳細(xì)解析的文章就介紹到這了,更多相關(guān)Java的ThreadLocal內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評論