最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

ThreadLocal內(nèi)存泄漏問(wèn)題解決方案

 更新時(shí)間:2020年09月15日 10:40:08   作者:小幾斤  
這篇文章主要介紹了ThreadLocal內(nèi)存泄漏問(wèn)題解決方案,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下

如果說(shuō) ThreadLocal 的話,那肯定就會(huì)涉及到內(nèi)存泄漏,為啥嘞

因?yàn)?吧啦吧啦 ~

ThreadLocal 解決了什么問(wèn)題呢?

它是為了解決對(duì)象不能被多線程共享訪問(wèn)的問(wèn)題,通過(guò) threadLocal.set() 方法將對(duì)象實(shí)例保存在每個(gè)線程自己所擁有的 threadLocalMap 中,這樣的話每個(gè)線程都使用自己的對(duì)象實(shí)例,彼此不會(huì)影響從而達(dá)到了隔離的作用,這樣就解決了對(duì)象在被共享訪問(wèn)時(shí)帶來(lái)的線程安全問(wèn)題。

啥意思呢?打個(gè)比方,現(xiàn)在公司所有人都要填寫一個(gè)表格,但是只有一支筆,這個(gè)時(shí)候就只能上個(gè)人用完了之后,下個(gè)人才可以使用,為了保證"筆"這個(gè)資源的可用性,只需要保證在接下來(lái)每個(gè)人的獲取順序就可以了,這就是 lock 的作用,當(dāng)這支筆被別人用的時(shí)候,我就加 lock ,你來(lái)了那就進(jìn)入隊(duì)列排隊(duì)等待獲取資源(非公平方式那就另外說(shuō)了),這支筆用完之后就釋放 lock ,然后按照順序給下個(gè)人使用。

但是完全可以一個(gè)人一支筆對(duì)不對(duì),這樣的話,你填寫你的表格,我填寫我的表格,咱倆誰(shuí)都不耽擱誰(shuí)。這就是 ThreadLocal 在做的事情,因?yàn)槊總€(gè) Thread 都有一個(gè)副本,就不存在資源競(jìng)爭(zhēng),所以也就不需要加鎖,這不就是拿空間去換了時(shí)間嘛!

在開(kāi)始之前,咱們先把 Thread, ThreadLocal, ThreadLocalMap 的關(guān)系捋一捋:

可以看到,在 Thread 中持有一個(gè) ThreadLocalMap , ThreadLocalMap 又是由 Entry 來(lái)組成的,在 Entry 里面有 ThreadLocal 和 value

ThreadLocal 為啥動(dòng)不動(dòng)就內(nèi)存泄漏呢?

在這里先給個(gè)解釋,后面咱們?cè)僭敿?xì)分析:

首先是因?yàn)?ThreadLocal 是基于 ThreadLocalMap 實(shí)現(xiàn)的,其中 ThreadLocalMap 的 Entry 繼承了 WeakReference ,而 Entry 對(duì)象中的 key 使用了 WeakReference 封裝,也就是說(shuō), Entry 中的 key 是一個(gè)弱引用類型,對(duì)于弱引用來(lái)說(shuō),它只能存活到下次 GC 之前

如果此時(shí)一個(gè)線程調(diào)用了 ThreadLocalMap 的 set 設(shè)置變量,當(dāng)前的 ThreadLocalMap 就會(huì)新增一條記錄,但由于發(fā)生了一次垃圾回收,這樣就會(huì)造成一個(gè)結(jié)果: key 值被回收掉了,但是 value 值還在內(nèi)存中,而且如果線程一直存在的話,那么它的 value 值就會(huì)一直存在

這樣被垃圾回收掉的 key 就會(huì)一直存在一條引用鏈: Thread -> ThreadLocalMap -> Entry -> Value :

就是因?yàn)檫@條引用鏈的存在,就會(huì)導(dǎo)致如果 Thread 還在運(yùn)行,那么 Entry 不會(huì)被回收,進(jìn)而 value 也不會(huì)被回收掉,但是 Entry 里面的 key 值已經(jīng)被回收掉了

這只是一個(gè)線程,如果再來(lái)一個(gè)線程,又來(lái)一個(gè)線程…多了之后就會(huì)造成內(nèi)存泄漏

知道是怎么造成內(nèi)存泄漏之后,接下來(lái)要做的事情就好說(shuō)了,不是因?yàn)?value 值沒(méi)有被回收掉所以才會(huì)導(dǎo)致內(nèi)存泄露的嘛

那使用完 key 值之后,將 value 值通過(guò) remove 方法 remove 掉,這樣的話內(nèi)存中就不會(huì)有 value 值了,也就防止了內(nèi)存泄漏嘛

ThreadLocal 是基于 ThreadLocalMap 實(shí)現(xiàn)的?

OK ,上面的內(nèi)容講完了,接下來(lái)一一來(lái)看

首先,你怎么知道 ThreadLocal 是基于 ThreadLocalMap 實(shí)現(xiàn)的呢?

從源碼知道的~

在源碼中能夠看到下面這幾行代碼:

public class ThreadLocal<T> { 
  static class ThreadLocalMap { 
    static class Entry extends WeakReference<ThreadLocal<?>> { 
      /** The value associated with this ThreadLocal. */ 
      Object value; 
 
      Entry(ThreadLocal<?> k, Object v) { 
        super(k); 
        value = v; 
      } 
    } 
  } 
} }   } }

代碼中說(shuō)的很清楚了,在 ThreadLocal 內(nèi)部維護(hù)著 ThreadLocalMap ,而它的 Entry 則繼承自 WeakReference 的 ThreadLocal ,其中 Entry 的 k 為 ThreadLocal , v 為 Object ,在調(diào)用 super(k) 時(shí)就將 ThreadLocal 實(shí)例包裝成了一個(gè) WeakReference

強(qiáng)弱引用這塊內(nèi)容阿粉就直接放一個(gè)表格吧:

引用類型 功能特點(diǎn)
強(qiáng)引用 ( Strong Reference ) 被強(qiáng)引用關(guān)聯(lián)的對(duì)象永遠(yuǎn)不會(huì)被垃圾回收器回收掉
軟引用( Soft Reference ) 軟引用關(guān)聯(lián)的對(duì)象,只有當(dāng)系統(tǒng)將要發(fā)生內(nèi)存溢出時(shí),才會(huì)去回收軟引用引用的對(duì)象
弱引用 ( Weak Reference ) 只被弱引用關(guān)聯(lián)的對(duì)象,只要發(fā)生垃圾收集事件,就會(huì)被回收
虛引用 ( Phantom Reference ) 被虛引用關(guān)聯(lián)的對(duì)象的唯一作用是能在這個(gè)對(duì)象被回收器回收時(shí)收到一個(gè)系統(tǒng)通知

從表格中應(yīng)該能夠看出來(lái),弱引用的對(duì)象只要發(fā)生垃圾收集事件,就會(huì)被回收

所以弱引用的存活時(shí)間也就是下次 GC 之前了

在這里阿粉就有個(gè)問(wèn)題想問(wèn)問(wèn)了:為什么 ThreadLocal 采用弱引用,而不是強(qiáng)引用嘞?

在 ThreadLocalMap 上面有些注釋,我在這里摘錄一部分,或許可以從中窺探一二:

To help deal with very large and long-lived usages, the hash table entries use WeakReferences for keys

翻譯一下就是:(雖然我英語(yǔ)不是很好

為了解決非常大且長(zhǎng)期使用的問(wèn)題,哈希表使用了弱引用的 key

假設(shè),假設(shè), ThreadLocal 使用的是強(qiáng)引用,會(huì)怎樣呢?

如果是強(qiáng)引用的話,在表格中也能夠看出來(lái),被強(qiáng)引用關(guān)聯(lián)的對(duì)象,永遠(yuǎn)都不會(huì)被垃圾回收器回收掉

如果引用的 ThreadLocal 對(duì)象被回收了,但是 ThreadLocalMap 還持有對(duì) ThreadLocal 的強(qiáng)引用,如果沒(méi)有 remove 的話, 在 GC 時(shí)進(jìn)行可達(dá)性分析, ThreadLocal 依然可達(dá),這樣就不會(huì)對(duì) ThreadLocal 進(jìn)行回收,但是我們期望的是引用的 ThreadLocal 對(duì)象被回收,這樣不就達(dá)不到目的了嘛

使用弱引用的話,雖然會(huì)出現(xiàn)內(nèi)存泄漏的問(wèn)題,但是在 ThreadLocal 生命周期里面,都有對(duì) key 值為 null 時(shí)進(jìn)行回收的處理操作

所以,使用弱引用的話,可以在 ThreadLocal 生命周期中盡可能保證不出現(xiàn)內(nèi)存泄漏的問(wèn)題

啥?在 ThreadLcoal 生命周期里面,都有對(duì) key 值為 null 時(shí)進(jìn)行回收的處理操作?有證據(jù)么?

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

最新評(píng)論

弋阳县| 礼泉县| 深州市| 旬邑县| 会宁县| 河间市| 天镇县| 龙里县| 同德县| 治多县| 灵宝市| 睢宁县| 元朗区| 桓台县| 瓦房店市| 北川| 四子王旗| 德昌县| 咸宁市| 马尔康县| 平邑县| 和林格尔县| 哈尔滨市| 徐水县| 湟中县| 简阳市| 太谷县| 长丰县| 黑水县| 介休市| 万山特区| 五河县| 周至县| 英吉沙县| 元江| 简阳市| 西乡县| 陆河县| 丹凤县| 垣曲县| 鸡泽县|