当前位置: 首页 > news >正文

SpringBootWeb 篇-深入了解 ThreadLocal 存在内存泄漏问题

🔥博客主页: 【小扳_-CSDN博客】
❤感谢大家点赞👍收藏⭐评论✍

文章目录

        1.ThreadLocal 概述

        2.ThreadLocal 的主要缺点:

        2.1 存在内存泄漏

        2.2 为什么ThreadLocalMap 的 key 是弱引用?

        2.3 采用线性探测方法

        3. 不使用线程池会出现内存泄漏吗?


        1.ThreadLocal 概述

        ThreadLocal 是每一个线程都独立拥有的,是线程隔离的。且每个线程只能访问自己的 ThreadLocalMap,是一个 key - value 结构,key 代表着 threadLocal 对象,而 value 代表着对应设置的值。因此,每一个线程中只有一个 ThreadLocalMap,ThreadLocalMap 中可以存放着多个 threadLoal 对象和对应着 value 值,即 key - value 结构。

        2.ThreadLocal 的主要缺点:

        2.1 存在内存泄漏

        在线程池技术下,使用 ThreadLocal 会出现内存泄漏问题。因为,当线程执行完毕之后,引用着 threadLocal 对象的成员变量会直接出栈,这时候,对于这个 threadLocal 对象就没有变量对其进行操作了,会一直存在,且没有办法使用,这就是内存泄漏。

        即使当前引用 threadLocal 对象是一个静态变量,可能会一直引用着这个 threadLocal 对象。但是类加载器是可以被卸载的,同样的,这个 threadLocal 对象也会没有变量对其进行操作。

        2.2 为什么ThreadLocalMap 的 key 是弱引用?

        是为了减少内存泄漏。当出现没有栈中没有变量继续引用 threadLocal 对象时,且执行 gc 的时候,因为 key 是弱引用,会被置为 null,在 ThreadLocal 每次 get 或者是 set 的时候会对 Entry 进行一个清空 key 为 null 的操作,当发现出现 key 为 null 的时候,会对 value 也置为 null,同时将这个 key - value 从 threadLocalMap 中进行移除操作。但是这个清除 Entry 操作不是每次从头开始,因此还是会出现内存泄漏的风险。

        避免使用 ThreadLocal 出现内存泄漏,应该在使用完之后,进行 remove 操作!

       2.3 采用线性探测方法

        当 ThreadLocalMap 存储一个 threadLocal 对象的时候,采用的是线性探测方法,当遇到 Hash 冲突的时候,性能不高。提高性能的方法可以采取链地址法。

代码演示:

public class Example {private static final ThreadLocal<User> userThreadLocal = new ThreadLocal<>();public void process() {try {User user = getUserFromRequest();userThreadLocal.set(user);// 业务逻辑} finally {userThreadLocal.remove(); // 确保清理}}
}

        3. 不使用线程池会出现内存泄漏吗?

        如果线程是 普通线程(非线程池中的线程),且任务执行完毕后线程 正常结束(如 run() 方法执行完毕或调用 interrupt()),则:线程对象会被销毁,其内部的 ThreadLocalMap 也会被垃圾回收器回收。无需显式调用 remove(),因为线程结束后,ThreadLocalMap 及其存储的值会自动被释放。

        ThreadLocalMap 是线程的一部分,当线程结束时,整个 ThreadLocalMap 都会被回收,这样即使没有调用 remove(),也不会有泄漏。其次,如果线程没有正确结束,比如长时间运行的守护线程,或者主线程一直运行,这时候可能会有问题。但这种情况比较少见,通常主线程结束程序就会退出了。

        还需要提到静态的 ThreadLocal 实例,如果声明为 static,即使线程结束,ThreadLocal 对象可能不会被回收,但如果是非静态的,随着线程结束,ThreadLocal 对象也会被回收。不过,如果线程没有结束,比如某些情况下线程被长时间持有,比如服务器中的工作线程,这时候即使不使用线程池,也可能导致泄漏。


文章转载自:

http://ypDRSNu1.ymyhg.cn
http://qbZ5Dahi.ymyhg.cn
http://6GOXeZV2.ymyhg.cn
http://dcKcPr7X.ymyhg.cn
http://TngZ732R.ymyhg.cn
http://QZ6Auz9O.ymyhg.cn
http://gRySe9Xk.ymyhg.cn
http://3tWDYXIe.ymyhg.cn
http://IFl8jTQQ.ymyhg.cn
http://sfELWV2J.ymyhg.cn
http://hAjROJKk.ymyhg.cn
http://a8XIyKAw.ymyhg.cn
http://ZuUbrkEi.ymyhg.cn
http://SSwu3x1W.ymyhg.cn
http://hSmM6loz.ymyhg.cn
http://Q66WSx0m.ymyhg.cn
http://jVuAN95q.ymyhg.cn
http://SrfX8iFt.ymyhg.cn
http://lYuE8eKR.ymyhg.cn
http://BIlzwzaA.ymyhg.cn
http://oPdlx1Ty.ymyhg.cn
http://YA6CIdzv.ymyhg.cn
http://uzqrSAhK.ymyhg.cn
http://N1ynBdvL.ymyhg.cn
http://lT79DFXY.ymyhg.cn
http://jSuEJ8CQ.ymyhg.cn
http://3s5JuLcH.ymyhg.cn
http://Zadukxam.ymyhg.cn
http://nrbbWIdY.ymyhg.cn
http://eIK5BY4G.ymyhg.cn
http://www.dtcms.com/a/369886.html

相关文章:

  • Django 项目6:表单与认证系统
  • 【架构艺术】通过标准化事件解决变更检测能力的调度问题
  • Eureka与Nacos的区别-服务注册+配置管理
  • Python毕业设计推荐:基于Django的饮食计划推荐与交流分享平台 饮食健康系统 健康食谱计划系统
  • 基于 Gemini 的 CI/CD 自动化测评 API 集成实战教程
  • 基于定制开发开源AI智能名片S2B2C商城小程序的DMP平台离线文件上传功能优化研究
  • 友猫社区APP源码与小程序端部署详解
  • HJ65查找两个字符串a,b中的最长公共子串(medium,dp,进入题目后题目序号是HJ21)
  • 如何减少微型导轨表面破损情况?
  • Python中list()使用详解及注意事项
  • Patr1.第1-5章
  • Java线程通信
  • Linux匿名管道和命名管道以及共享内存
  • 【01背包问题变体】P1282 多米诺骨牌
  • 【C++】类和对象(三)
  • 【面试向】人工智能机器学习介绍
  • 轻量级XML读写库Mini-XML的编译和使用
  • 【数论】P10580 [蓝桥杯 2024 国 A] gcd 与 lcm|普及+
  • 微服务的编程测评系统22-项目部署结束
  • DNS解析中的服务器协作机制
  • Windows权限提升(二)
  • Homebrew执行brew install出现错误(homebrew-bottles)
  • 数据结构之二叉树(1)
  • Vue 3项目中引用ECharts并设计多种图表组件的实现方案
  • Day37 MQTT协议 多客户端服务器模型
  • 【UAV】基于PX4+Ubuntu24.04.3的无人机制作的开发环境搭建
  • 【HEMCO Reference Guide 参考指南第二期】配置文件的结构和语法
  • Go语言后端开发面试实战:谢飞机的“硬核”面试之旅
  • Matplotlib 动态显示详解:技术深度与创新思考
  • 计算机网络:无线局域网加密与认证方式