对ThreadLocal内存泄漏问题的简单了解

ThreadLocal 中填充的的是当前线程的变量,该变量对其他线程而言是封闭且隔离的,ThreadLocal 为变量在每个线程中创建了一个副本,这样每个线程都可以访问自己内部的副本变量。其有如下特点:

  • 1、在进行对象跨层传递的时候,使用ThreadLocal可以避免多次传递,打破层次间的约束。(如从控制层,服务层,持久层)
  • 2、线程间数据隔离
  • 3、进行事务操作,用于存储线程事务信息。
  • 4、数据库连接,Session会话管理。

在这里插入图片描述

ThreadLocalMapThreadLocal 的一个静态内部类,里面定义了Entry 来保存数据。而且是继承的弱引用。在Entry内部使用ThreadLocal作为key,使用我们设置的value作为value

对于每个线程内部有个ThreadLocal.ThreadLocalMap 变量,存取值的时候,也是从这个容器中来获取。

//threadlocal存入数据方法
public void set(T value){
    //获取当前线程对象
    Thread t=Thread.currentThread();
    //将当前线程作为入参 得到ThreadLocalMap (类似Map)
    ThreadLocalMap map =getMap(t);
    if(map!=null){
        //map不为空写入this :ThreadLocal对象
        map.set(this,value);
    }else{
        //map为空,先创建再写入
        createMap(t,value)}
}

这样设计的好处是,如果这个变量不再被其他对象使用时,可以自动回收这个ThreadLocal对象,以此避免可能的内存泄露。

如果key设为强引用,假如JVM中存在大量线程都在运行,导致JVM中存在大量ThreadLocal对象无法被回收(内存泄漏-GC 无法清理这块内存区域)。大量内存泄漏会导致内存溢出。

Key对应ThreadLocal只要发生GC就会被回收,Key变为null,Entry中Value无法被访问,随着类似线程不断存入数据,Value是不可访问对象会导致内存泄漏最终导致OOM。

使用了线程池,可以达到“线程复用”的效果。但是归还线程之前记得清除ThreadLocalMap,要不然再取出该线程的时候,ThreadLocal变量还会存在。这就不仅仅是内存泄露的问题了,整个业务逻辑都可能会出错。

写入ThreadLocal中数据用完以后一定要立即手动清除。

要防止 ThreadLocal 内存泄漏,可以考虑以下方法:

使用完 ThreadLocal 后及时调用 remove() 方法:在不再需要使用 ThreadLocal 存储的数据时,手动调用 ThreadLocal.remove() 方法将该数据从当前线程的 ThreadLocalMap 中清除。这样可以确保 ThreadLocalMap 不会持有对对象的引用,从而帮助垃圾回收器正常回收不再需要的对象。

javaCopy code
ThreadLocal<Object> threadLocal = new ThreadLocal<>();
// 存储数据
threadLocal.set(someData);
// 使用完毕后清除
threadLocal.remove();

使用 try-with-resources 或 try-finally 块:如果你的 ThreadLocal 变量在需要清理的资源管理上下文中使用,可以使用 try-with-resources(自动清理)或 try-finally(手动清理)块来确保及时清理。

javaCopy code
try (ThreadLocalResource resource = new ThreadLocalResource()) {
    // 使用 ThreadLocalResource
}
// 或者使用 try-finally
ThreadLocalResource resource = new ThreadLocalResource();
try {
    // 使用 ThreadLocalResource
} finally {
    resource.close(); // 在 close 方法中清理 ThreadLocal 变量
}

使用 InheritableThreadLocal:如果需要在子线程中访问父线程的 ThreadLocal 变量,并且确保在子线程中正确清理,可以考虑使用 InheritableThreadLocal。这个类允许子线程继承父线程的 ThreadLocal 变量,并在子线程完成后自动清理。

javaCopy code
ThreadLocal<String> threadLocal = new InheritableThreadLocal<>();
threadLocal.set("Hello, Parent Thread");
Runnable childTask = () -> {
    String value = threadLocal.get(); // 子线程可以访问父线程的 ThreadLocal 变量
    // ...
};
Thread childThread = new Thread(childTask);
childThread.start();

通过采取这些预防措施,可以有效避免 ThreadLocal 变量的内存泄漏问题,确保不再需要的对象能够被及时回收。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/342074.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

高清短视频素材网站有哪些?分享十个做短视频必备的素材下载网站!

对于专注于短视频制作和剪辑的朋友来说&#xff0c;找到高质量的视频素材至关重要。你可能会想&#xff1a;“高清短视频素材网站有哪些&#xff1f;”别担心&#xff0c;今天我要为大家推荐十个提供优质素材的网站&#xff0c;帮你轻松搞定短视频制作&#xff01; 怪木素材网…

TypeScript 实用技巧(中)

十四、向类型添加特殊值 原文&#xff1a;exploringjs.com/tackling-ts/ch_special-values.html 译者&#xff1a;飞龙 协议&#xff1a;CC BY-NC-SA 4.0 14.1 在带内添加特殊值 14.1.1 向类型添加 null 或 undefined 14.1.2 向类型添加符号 14.2 在带外添加特殊值 14.2…

C++ 类定义

C 类定义 定义一个类需要使用关键字 class&#xff0c;然后指定类的名称&#xff0c;并类的主体是包含在一对花括号中&#xff0c;主体包含类的成员变量和成员函数。 定义一个类&#xff0c;本质上是定义一个数据类型的蓝图&#xff0c;它定义了类的对象包括了什么&#xff0…

Unity SRP 管线【第五讲:URP烘培光照】

本节&#xff0c;我们将跟随数据流向讲解UEP管线中的烘培光照。 文章目录 一、URP烘培光照1. 搭建场景2. 烘培光照参数设置MixedLight光照设置&#xff1a;直观感受 Lightmapping Settings参数设置&#xff1a; 3. 我们如何记录次表面光源颜色首先我们提取出相关URP代码&#…

day22-线程

今天的内容【重要&#xff01;&#xff01;&#xff01;】 1.进程 2.线程【重点】 1.什么是进程 是独立的运行程序 ​ 比如咱们电脑软件&#xff0c;你启动起来以后&#xff0c;他就是一个进程。qq idea 进程需要windows系统的分配。可以获取当前的系统的网卡&#xff0c;内存&…

重拾计网-第四弹 计算机网络性能指标

ps&#xff1a;本文章的图片内容来源都是来自于湖科大教书匠的视频&#xff0c;声明&#xff1a;仅供自己复习&#xff0c;里面加上了自己的理解 这里附上视频链接地址&#xff1a;1.5 计算机网络的性能指标&#xff08;1&#xff09;_哔哩哔哩_bilibili ​​​ 目录 &#x…

Mac使用adb调试安卓手机

0x00 背景 最近windows电脑休息&#xff0c;用mac办公比较多&#xff0c;手机用时间长了&#xff0c;不太灵光&#xff0c;准备修理一番。于是要用mac调试下android手机。配置略显麻烦&#xff0c;网上的步骤多参差不齐。估计是入门步骤&#xff0c;大佬们也懒得写的太细。于是…

适用于电动汽车充电站箱变的电气安全物联监测系统设计方案——安科瑞赵嘉敏

摘 要&#xff1a; 基于物联网技术架构提出了一种适用于电动汽车充电站箱变的电气安全物联监测系统设计方案。该系统由 电气安全智能感知设备、通信网关、电气安全物联网监测平台等构成&#xff0c;可支持充电站箱变充电桩出线回路电流、电缆 温度、剩余电流、故障电弧、短路…

java(渣哇)------输入与输出语句(详解) (๑•̌.•๑)

目录 一.java的输出语句&#xff1a; System.out.println() -----输出并换行 System.out.print() -----输出但不换行 System.out.printf() -----类似C语言的printf()输出语句,按格式进行输出 二.java的输入语句&#xff1a; 2.1-----Scanner的基础用法&#xff1a; 2.2…

JadxGUI反编译工具

安卓应用获取App特征信息指导 包名、公钥和签名MD5获取方式有多种&#xff0c;本文以使用JadxGUI工具获取为例。 下载地址&#xff1a; https://download.csdn.net/download/guodashen007/88772567 下载JadxGUI工具&#xff1a;下载安装完成后&#xff0c;使用此工具打开apk包…

聪明购物秘籍:如何规避Shopee账号关联封号风险

在Shopee平台上&#xff0c;规定一个买家只能拥有一个买家号&#xff0c;同时在一台电脑或者一个手机上登录多个买家号可能导致关联封号的风险。为了规避这一风险&#xff0c;许多购物达人正在寻找方法来防止账号关联。下面是一些使用大量Shopee买家号的技巧&#xff0c;帮助您…

决策树的基本构建流程

决策树的基本构建流程 决策树的本质是挖掘有效的分类规则&#xff0c;然后以树的形式呈现。 这里有两个重点&#xff1a; 有效的分类规则&#xff1b;树的形式。 有效的分类规则&#xff1a;叶子节点纯度越高越好&#xff0c;就像我们分红豆和黄豆一样&#xff0c;我们当然…

增速下滑?毫米波雷达的「烦恼」

编者按&#xff1a;传统3D雷达不赚钱&#xff0c;4D雷达还处于市场导入初期&#xff0c;对于不同角色的供应商来说&#xff0c;当下最难的是如何熬过这段艰难时期。 2023年底&#xff0c;蔚来旗舰车型ET9正式亮相&#xff0c;首次导入4D毫米波成像雷达。这款产品由蔚来资本投资…

GLM-4多模态重磅更新!摸着OpenAI过河!

智谱CEO张鹏说&#xff1a;OpenAI摸着石头过河&#xff0c;我们摸着OpenAI过河。 摸来摸去摸了一年&#xff0c;以每3-4个月升级一次基座模型的速度&#xff0c;智谱摸着OpenAI过河的最新成绩到底怎么样&#xff1f;真如所说吗&#xff1f; 听到GLM-4发布的当天&#xff0c;我就…

Android14实战:调整A2DP音量曲线(五十三)

简介: CSDN博客专家,专注Android/Linux系统,分享多mic语音方案、音视频、编解码等技术,与大家一起成长! 优质专栏:Audio工程师进阶系列【原创干货持续更新中……】🚀 优质专栏:多媒体系统工程师系列【原创干货持续更新中……】🚀 人生格言: 人生从来没有捷径,只…

Rust采集天气预报信息并实时更新数据

目录 一、引言 二、系统设计 三、系统实现 四、案例分析 五、结论 一、引言 随着互联网技术的发展&#xff0c;人们对于获取实时的天气预报信息的需求越来越强烈。Rust作为一种高效、安全的编程语言&#xff0c;可以用于开发各种应用&#xff0c;包括天气预报采集系统。本…

Unity中URP下的 额外灯 逐像素光 和 逐顶点光

文章目录 前言一、额外灯 的 逐像素灯 和 逐顶点灯1、存在额外灯的逐像素灯2、存在额外灯的逐顶点灯 二、测试这两个宏的作用1、额外灯的逐像素灯2、额外灯的逐顶点灯 前言 在之前的文章中&#xff0c;我们了解了 主光相关的反射计算。 Unity中URP下的SimpleLit的 Lambert漫反…

图解CART分类树评估器的参数

图解CART分类树评估器的参数

微信小程序从入门到进阶(二)

数据请求 wx.request发起网络请求&#xff0c;请求的方式主要分为两种&#xff1a; get 请求 post 请求 // get请求 // html <view><button type"primary" bindtap"onGetClick">发起 get 请求</button> </view> // js // inde…

解决报错:javax.net.ssl.SSLHandshakeException: No appropriate protocol

目录 一、场景二、报错信息三、原因四、排查五、解决 一、场景 使用对象存储进行文件上传时报错 注&#xff1a;该问题只要需要用到http的都有可能出现&#xff0c;不是只针对对象存储 二、报错信息 com.hitachivantara.hcp.common.ex.InvalidResponseException: com.hitach…
最新文章