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.mzph.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…