ThreadLocal的內存泄漏

  1. 什么是內存泄漏

    1. 程序在申請內存后,無法釋放已申請的內存空間
    2. 在定義變量時,需要一段內存空間來存儲數據信息,而這段內存如果一直不被釋放,那么就會導致內存被占用光,而被占用的這個對象,一直不能被回收掉,這就是內存泄漏
  2. ThreadLocal

    1. private ThreadLocalMap(ThreadLocalMap parentMap) {Entry[] parentTable = parentMap.table;int len = parentTable.length;setThreshold(len);table = new Entry[len];for (int j = 0; j < len; j++) {Entry e = parentTable[j];if (e != null) {@SuppressWarnings("unchecked")ThreadLocal<Object> key = (ThreadLocal<Object>) e.get();if (key != null) {Object value = key.childValue(e.value);Entry c = new Entry(key, value);int h = key.threadLocalHashCode & (len - 1);while (table[h] != null)h = nextIndex(h, len);table[h] = c;size++;}}}}
      
    2. 每一個ThreadLocal維護一個ThreadLocalMap,key為使用弱引用的ThreadLocal實例,value為線程變量的副本

  3. 強引用

    1. 使用最普遍的引用,一個對象具有強引用,不會被垃圾回收器回收,當內存空間不足,JAVA虛擬機寧愿拋出OOM錯誤,使程序異常終止,也不會受這種對象
    2. 如果想取消強引用和某個對象之間的關聯,可以顯示地將引用賦值為null,這樣可以使JVM在合適的時間就會回收該對象
  4. 弱引用

    1. JVM進行垃圾回收時,無論是內存是否充足,都會回收被弱引用關聯的對象,在java中,用java.lang.ref.WeakReference類來表示,可以在緩存中使用弱引用
  5. 內存泄漏

    1. ThreadLocalMap使用ThreadLocal的弱應用作為key,如果一個ThreadLocal不存在外部強引用,Key勢必會被GC回收,這樣就導致ThreadLocal中key為null,而value還存在著強引用,只有Thread線程退出以后,value的強引用鏈條才會斷掉
    2. 如果當前線程遲遲不結束,這些key為null的Entry的value就會一直存在一條強引用鏈
    3. Thread Ref -> Thread -> ThreadLocalMap ->Entry -> value
    4. 這個時候,永遠無法回收,就會造成ThreadLocal出現內存泄漏的問題
  6. 如果ThreadLocalMap使用ThreadLocal的強引用

    1. 因為ThreadLocalMap還持有ThreadLocal的強引用,如果沒有手動刪除,ThreadLocal不會被回收,導致Entry內存泄漏
    2. 當ThreadLocalMap的key為弱引用回收ThreadLocal時,由于ThreadLocalMap持有ThreadLocal的弱引用,即使沒有手動刪除,ThreadLocal也會被回收,當key為null,在下一次ThreadLocalMap調用set和get,remove方法時會被清除value的值
  7. 為什么使用弱引用

    1. 因為使用弱引用可以多一層保障,弱引用ThreadLocal不會內存泄漏,對應的value在下一次ThreadLocalMap調用set,get,remove時會被清除

    2. 因此,ThreadLocal內存泄漏的根本原因是:由于ThreadLocalMap的生命周期跟Thread一樣長,如果沒有手動刪除對應的key就會導致內存泄漏,而不是因為弱引用

    3. static class ThreadLocalMap {//hreadLocalMap中數據是存儲在Entry類型數組的table中的,Entry繼承了WeakReference(弱引用)static class Entry extends WeakReference<ThreadLocal<?>> {Object value;Entry(ThreadLocal<?> k, Object v) {super(k);value = v;}}**成員變量**
      //初始容量 
      private static final int INITIAL_CAPACITY = 16;//ThreadLocalMap數據真正存儲在table中
      private Entry[] table;//ThreadLocalMap條數        
      private int size = 0;//達到這個大小,則擴容       
      private int threshold; 
    4. 構造函數

      1. ThreadLocalMap(ThreadLocal<?> firstKey, Object firstValue) {//初始化table數組,INITIAL_CAPACITY默認值為16table = new Entry[INITIAL_CAPACITY];//key和16取得哈希值int i = firstKey.threadLocalHashCode & (INITIAL_CAPACITY - 1);//創建節點,設置key-valuetable[i] = new Entry(firstKey, firstValue);size = 1;//設置擴容閾值setThreshold(INITIAL_CAPACITY);
        }
        
    5. remove方法

      1. private void remove(ThreadLocal<?> key) {Entry[] tab = table;int len = tab.length;int i = key.threadLocalHashCode & (len-1);//如果threadLocalHashCode計算出的下標找到的key和傳入key不同,則證明出現哈希沖突,則循環向下查找for (Entry e = tab[i];e != null;e = tab[i = nextIndex(i, len)]) {//如果key相同if (e.get() == key) {//刪除當前Entrye.clear();//清理expungeStaleEntry(i);return;}}}
        
  8. 解決方法

    1. 每次使用完ThreadLocal都調用他的remove方法清除數據
    2. 將ThreadLocal變量定義為private static,這樣就一直存在ThreadLocal的強引用,也就是保證任何時候都能通過ThreadLocal的弱引用訪問到Entry的value值,進而清除掉

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/42720.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/42720.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/42720.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

書生·浦語2.5開源,推理能力再創新標桿

導讀 2024 年 7 月 3 日&#xff0c;上海人工智能實驗室與商湯科技聯合香港中文大學和復旦大學正式發布新一代大語言模型書?浦語2.5&#xff08;InternLM2.5&#xff09;。相比上一代模型&#xff0c;InternLM2.5 有三項突出亮點&#xff1a; 推理能力大幅提升&#xff0c;在…

VUE與React的生命周期對比

前言 在前端開發中&#xff0c;Vue和React是兩個非常流行的JavaScript框架&#xff0c;它們各自有著獨特的生命周期機制。了解并熟練掌握這些生命周期&#xff0c;對于開發高效、可維護的前端應用至關重要。本文將詳細對比Vue和React的生命周期&#xff0c;幫助開發者更好地理…

Python | Leetcode Python題解之第222題完全二叉樹的節點個數

題目&#xff1a; 題解&#xff1a; # Definition for a binary tree node. # class TreeNode: # def __init__(self, val0, leftNone, rightNone): # self.val val # self.left left # self.right right class Solution:def countNodes(self,…

好玩的珠璣妙算-加作弊帶概率空間+日志存儲240705mindMaster

Python代碼 import random import time import datetimeNUM_DIGITS 10 #NUM_NON_ZERO_DIGITS 9failFlag 0class Mastermind:def __init__(self, code_length, max_attempts, secret01code, game_id): # def __init__(self, code_length, max_attempts):self.code_length…

【Elasticsearch】Elasticsearch倒排索引詳解

文章目錄 &#x1f4d1;引言一、倒排索引簡介二、倒排索引的基本結構三、Elasticsearch中的倒排索引3.1 索引和文檔3.2 創建倒排索引3.3 倒排索引的存儲結構3.4 詞典和倒排列表的優化 四、倒排索引的查詢過程4.1 過程4.2 示例 五、倒排索引的優缺點5.1 優點5.2 缺點 六、倒排索…

【Excel】求和帶文字的數據

目錄標題 1. 給出樣例2. CtrlE3. CtrlH → A替換為 → 全部替換 1. 給出樣例 2. CtrlE 3. CtrlH → A替換為 → 全部替換

算法期末函數題

R6-1 可重復選擇的組合數問題 【考核知識點】可重復選擇的組合計數 【問題描述】 有n個不同元素&#xff08;1<n<20&#xff09;&#xff0c;每個元素可以選多次&#xff0c;一共需要選出k個元素出來&#xff08;1<k<20&#xff09;&#xff0c;問有多少種選取的…

監控易V7.6.6.15升級詳解2:設備管理功能

隨著企業IT架構的日益復雜&#xff0c;對設備管理的需求也在不斷提升。為了滿足廣大用戶對于設備管理的高效、精準需求&#xff0c;我們榮幸地宣布監控易系統已完成了一次重要的版本升級。本次升級不僅優化了原有功能&#xff0c;還新增了一系列實用特性&#xff0c;旨在為用戶…

仿qq音樂播放微信小程序模板源碼

手機qq音樂應用小程序&#xff0c;在線音樂播放器微信小程序網頁模板。包含&#xff1a;音樂歌曲主頁、推薦、排行榜、搜索、音樂播放器、歌單詳情等。 仿qq音樂播放微信小程序模板源碼

【ubuntu自啟shell腳本】——在ubuntu中如何使用系統自帶的啟動應用程序設置開機自啟自己的本地shell腳本

提示&#xff1a;文章寫完后&#xff0c;目錄可以自動生成&#xff0c;如何生成可參考右邊的幫助文檔 文章目錄 前言一、設置開機自啟shell腳本1.使用 gnome-session-properties2.測試的shell例程代碼 總結 前言 在Ubuntu系統中設置開機自啟腳本是一種重要的自動化方法。開機自…

YOLO-World實時開集檢測論文閱讀

論文&#xff1a;《YOLO-World: Real-Time Open-Vocabulary Object Detection》 代碼&#xff1a;https://github.com/AILab-CVC/YOLO-World 1.Abstract 我們介紹了YOLO World&#xff0c;這是一種創新的方法&#xff0c;通過在大規模數據集上進行視覺語言建模和預訓練&#…

js之彈性布局使用方法

彈性布局&#xff08;Flexbox&#xff09;是一種現代化的 CSS 布局方法&#xff0c;它可以讓您更方便地創建響應式和動態布局。在本篇文檔中&#xff0c;我們將介紹彈性布局的基本概念以及如何在項目中使用它。 一、基本概念 容器&#xff08;Container&#xff09;&#xff…

WPF中邏輯樹和視覺樹

在WPF&#xff08;Windows Presentation Foundation&#xff09;中&#xff0c;“邏輯樹”&#xff08;Logical Tree&#xff09;和“可視樹”&#xff08;Visual Tree&#xff09;是兩個重要的概念&#xff0c;它們代表了不同的對象層次結構&#xff0c;用于描述應用程序的組織…

洛谷 [SNCPC2024] 寫都寫了,交一發吧 題解

分析 顯然&#xff0c;兩個相同的數去按位與的結果還是該數。 由于一個代碼可以提交多次&#xff0c;那么可以把得分最高的代碼提交兩次&#xff0c;這樣的得分就是這個代碼的得分&#xff0c;很明顯&#xff0c;這樣是最優的。 Code #include<iostream> using names…

STM32微控制器的SPI存儲解決方案:W25Q64 Flash存儲器深度應用

摘要 在嵌入式系統設計中&#xff0c;存儲解決方案對于數據的持久化至關重要。W25Q64 Flash存儲器以其高效的存儲能力和與SPI總線的兼容性&#xff0c;成為STM32微控制器項目中的優選。本文將深入探討STM32微控制器的SPI存儲解決方案&#xff0c;重點介紹W25Q64 Flash存儲器的…

vue3+antd 實現點擊按鈕彈出對話框

格式1&#xff1a;確認對話框 按鈕&#xff1a; 點擊按鈕之后&#xff1a; 完整代碼&#xff1a; <template><div><a-button click"showConfirm">Confirm</a-button></div> </template> <script setup> import {Mod…

如何查看程序是否在運行-Linux

1.命令 ps aux | grep RiboCode2_manythreads.py2.結果&#xff1a; 2020200 1063124 99.8 19.2 56105444 50796184 pts/0 Sl 18:40 114:36 python RiboCode2_manythreads.py -a ./RiboCode_annot -c config15d.txt -o ./ORFs_15d_final_result --gtf -t 15從輸出結果可以看出…

階段三:項目開發---大數據開發運行環境搭建:任務4:安裝配置Spark集群

任務描述 知識點&#xff1a;安裝配置Spark 重 點&#xff1a; 安裝配置Spark 難 點&#xff1a;無 內 容&#xff1a; Apache Spark 是專為大規模數據處理而設計的快速通用的計算引擎。Spark是UC Berkeley AMP lab (加州大學伯克利分校的AMP實驗室)所開源的類Hadoop …

Bean的管理

1.主動獲取Bean spring項目在需要時&#xff0c;會自動從IOC容器中獲取需要的Bean 我們也可以自己主動的得到Bean對象 &#xff08;1&#xff09;獲取bean對象&#xff0c;首先獲取SpringIOC對象 private ApplicationContext applicationContext //IOC容器對象 (2 )方法…

昇思25天學習打卡營第13天 | ShuffleNet圖像分類

ShuffleNet網絡介紹 ShuffleNetV1是曠視科技提出的一種計算高效的CNN模型&#xff0c;和MobileNet, SqueezeNet等一樣主要應用在移動端&#xff0c;所以模型的設計目標就是利用有限的計算資源來達到最好的模型精度。ShuffleNetV1的設計核心是引入了兩種操作&#xff1a;Pointw…