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

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

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

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

因為 吧啦吧啦 ~

ThreadLocal 解決了什么問題呢?

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

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

但是完全可以一個人一支筆對不對,這樣的話,你填寫你的表格,我填寫我的表格,咱倆誰都不耽擱誰。這就是 ThreadLocal 在做的事情,因為每個 Thread 都有一個副本,就不存在資源競爭,所以也就不需要加鎖,這不就是拿空間去換了時間嘛!

在開始之前,咱們先把 Thread, ThreadLocal, ThreadLocalMap 的關系捋一捋:

可以看到,在 Thread 中持有一個 ThreadLocalMap , ThreadLocalMap 又是由 Entry 來組成的,在 Entry 里面有 ThreadLocal 和 value

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

在這里先給個解釋,后面咱們再詳細分析:

首先是因為 ThreadLocal 是基于 ThreadLocalMap 實現(xiàn)的,其中 ThreadLocalMap 的 Entry 繼承了 WeakReference ,而 Entry 對象中的 key 使用了 WeakReference 封裝,也就是說, Entry 中的 key 是一個弱引用類型,對于弱引用來說,它只能存活到下次 GC 之前

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

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

就是因為這條引用鏈的存在,就會導致如果 Thread 還在運行,那么 Entry 不會被回收,進而 value 也不會被回收掉,但是 Entry 里面的 key 值已經(jīng)被回收掉了

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

知道是怎么造成內(nèi)存泄漏之后,接下來要做的事情就好說了,不是因為 value 值沒有被回收掉所以才會導致內(nèi)存泄露的嘛

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

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

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

首先,你怎么知道 ThreadLocal 是基于 ThreadLocalMap 實現(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; 
      } 
    } 
  } 
} }   } }

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

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

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

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

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

在這里阿粉就有個問題想問問了:為什么 ThreadLocal 采用弱引用,而不是強引用嘞?

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

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

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

為了解決非常大且長期使用的問題,哈希表使用了弱引用的 key

假設,假設, ThreadLocal 使用的是強引用,會怎樣呢?

如果是強引用的話,在表格中也能夠看出來,被強引用關聯(lián)的對象,永遠都不會被垃圾回收器回收掉

如果引用的 ThreadLocal 對象被回收了,但是 ThreadLocalMap 還持有對 ThreadLocal 的強引用,如果沒有 remove 的話, 在 GC 時進行可達性分析, ThreadLocal 依然可達,這樣就不會對 ThreadLocal 進行回收,但是我們期望的是引用的 ThreadLocal 對象被回收,這樣不就達不到目的了嘛

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

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

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

以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。

相關文章

  • Windows安裝Maven并配置環(huán)境的詳細步驟

    Windows安裝Maven并配置環(huán)境的詳細步驟

    Maven是一個非常流行的構建和項目管理工具,用于Java開發(fā),它提供了一個強大的依賴管理系統(tǒng)和一系列標準化的構建生命周期,本文將指導您如何在Windows操作系統(tǒng)上安裝和配置Maven,需要的朋友可以參考下
    2023-05-05
  • java實現(xiàn)手機短信驗證的基本思路

    java實現(xiàn)手機短信驗證的基本思路

    這篇文章主要為大家詳細介紹了java實現(xiàn)手機短信驗證的基本思路,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-11-11
  • 解決springboot+shiro+thymeleaf頁面級元素的權限控制問題

    解決springboot+shiro+thymeleaf頁面級元素的權限控制問題

    這篇文章主要介紹了解決springboot+shiro+thymeleaf頁面級元素的權限控制問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-01-01
  • java Split 實現(xiàn)去除一個空格和多個空格

    java Split 實現(xiàn)去除一個空格和多個空格

    這篇文章主要介紹了java Split 實現(xiàn)去除一個空格和多個空格,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-10-10
  • 一步步教你搭建Scala開發(fā)環(huán)境(非常詳細!)

    一步步教你搭建Scala開發(fā)環(huán)境(非常詳細!)

    Scala是一門基于jvm的函數(shù)式的面向?qū)ο缶幊陶Z言,擁有比java更加簡潔的語法,下面這篇文章主要給大家介紹了關于搭建Scala開發(fā)環(huán)境的相關資料,文中通過圖文介紹的非常詳細,需要的朋友可以參考下
    2022-04-04
  • Java8 中使用Stream 讓List 轉 Map使用問題小結

    Java8 中使用Stream 讓List 轉 Map使用問題小結

    這篇文章主要介紹了Java8 中使用Stream 讓List 轉 Map使用總結,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-06-06
  • 詳細全面解析Java泛型

    詳細全面解析Java泛型

    這篇文章主要介紹了詳細全面解析Java泛型,java泛型主要提高了Java 程序的類型安全,通過知道使用泛型定義的變量的類型限制,編譯器可以驗證類型假設,消除源代碼中的許多強制類型轉換等多個有點,下面我們進入文章了解更多的詳細內(nèi)容吧
    2022-02-02
  • Spring?Security中如何獲取AuthenticationManager對象

    Spring?Security中如何獲取AuthenticationManager對象

    有時需要使用AuthenticationManager(以下簡稱Manager)對象,可是這個對象不是Bean,沒有直接保存在Spring的Bean庫中,那么如何獲取Spring Security中的這個對象呢,需要的朋友可以參考下
    2022-11-11
  • springmvc直接不經(jīng)過controller訪問WEB-INF中的頁面問題

    springmvc直接不經(jīng)過controller訪問WEB-INF中的頁面問題

    這篇文章主要介紹了springmvc直接不經(jīng)過controller訪問WEB-INF中的頁面問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-02-02
  • Spring如何消除代碼中的if-else/switch-case

    Spring如何消除代碼中的if-else/switch-case

    這篇文章主要給大家介紹了關于Spring如何消除代碼中if-else/switch-case的相關資料,文中通過示例代碼介紹的非常詳細,對大家學習或者使用Spring具有一定的參考學習價值,需要的朋友們下面來一起學習學習吧
    2019-04-04

最新評論