ThreadLocal 内存泄漏问题深入分析
写在前面
ThreadLocal 基本用法本文就不介绍了,如果有不知道的小伙伴可以先了解一下,本文只研究 ThreadLocal 内存泄漏这一问题。
ThreadLocal 会发生内存泄漏吗?
先给出结论:如果你使用不当是有可能发生内存泄露的

ThreadLocal 和 当前 Thread 栈堆布局图
每个 Thread 里面都有一个 ThreadLocalMap,而 ThreadLocalMap 中真正承载数据的是一个 Entry 数组,Entry 的 Key 是 threadlocal 对象的弱引用。
这里或许有的小伙伴有疑问,Entry 的 Key 是 threadlocal 对象的弱引用,为什么要用弱引用,换成强引用行不行?
首先,我们先了解一下什么是弱引用?
弱引用一般是用来描述非必需对象的,被弱引用关联的对象只能生存到下一次垃圾收集发生之前。当垃圾收集器工作时,无论当前内存是否足够,都会回收掉只被弱引用关联的对象。
实际开发中,当我们不需要 threadlocal 后,为了 GC 将 threadlocal 变量置为 null,没有任何强引用指向堆中的 threadlocal 对象时,堆中的 threadlocal 对象将会被 GC 回收,假设现在 Key 持有的是 threadlocal 对象的强引用,如果当前线程仍然在运行,那么从当前线程一直到 threadlocal 对象还是存在强引用,由于当前线程仍在运行的原因导致 threadlocal 对象无法被 GC,这就发生了内存泄漏。相反,弱引用就不存在此问题,当栈中的 threadlocal 变量置为 null 后,堆中的 threadlocal 对象只有一个 Key 的弱引用关联,下一次 GC 的时候堆中的 threadlocal 对象就会被回收,使用弱引用对于 threadlocal 对象而言是不会发生内存泄漏的。
那么,第二个问题来了,是不是 Key 持有的是 threadlocal 对象的弱引用就一定不会发生内存泄漏呢?
结论是:如果你使用不当还是有可能发生内存泄露,但是,这里发生内存泄漏的地方和上面不同。
当 threadlocal 使用完后,将栈中的 threadlocal 变量置为 null,threadlocal 对象下一次 GC 会被回收,那么 Entry 中的与之关联的弱引用 key 就会变成 null,如果此时当前线程还在运行,那么 Entry 中的 key 为 null 的 Value 对象并不会被回收(存在强引用),这就发生了内存泄漏,当然这种内存泄漏分情况,如果当前线程执行完毕会被回收,那么 Value 自然也会被回收,但是如果使用的是线程池呢,线程跑完任务以后放回线程池(线程没有销毁,不会被回收),Value 会一直存在,这就发生了内存泄漏。
如何更好的降低内存泄漏的风险呢?
ThreadLocal 为了降低内存泄露的可能性,在 set,get,remove 的时候都会清除此线程 ThreadLocalMap 里 Entry 数组中所有 Key 为 null 的 Value。所以,当前线程使用完 threadlocal 后,我们可以通过调用 ThreadLocal 的 remove 方法进行清除从而降低内存泄漏的风险。
最后
如果大家想要实时关注我更新的文章以及我分享的干货的话,可以关注我的公众号 我们都是小白鼠。

ThreadLocal 内存泄漏问题深入分析的更多相关文章
- 深入分析 ThreadLocal 内存泄漏问题
前言 ThreadLocal 的作用是提供线程内的局部变量,这种变量在线程的生命周期内起作用,减少同一个线程内多个函数或者组件之间一些公共变量的传递的复杂度.但是如果滥用ThreadLocal,就可能 ...
- java多线程--------深入分析 ThreadLocal 内存泄漏问题
前言 ThreadLocal 的作用是提供线程内的局部变量,这种变量在线程的生命周期内起作用,减少同一个线程内多个函数或者组件之间一些公共变量的传递的复杂度.但是如果滥用ThreadLocal,就可能 ...
- 分析 ThreadLocal 内存泄漏问题
ThreadLocal 的作用是提供线程内的局部变量,这种变量在线程的生命周期内起作用,减少同一个线程内多个函数或者组件之间一些公共变量的传递的复杂度.但是如果滥用 ThreadLocal,就可能会导 ...
- 18.一篇文章,从源码深入详解ThreadLocal内存泄漏问题
1. 造成内存泄漏的原因? threadLocal是为了解决对象不能被多线程共享访问的问题,通过threadLocal.set方法将对象实例保存在每个线程自己所拥有的threadLocalMap中,这 ...
- ThreadLocal内存泄漏真因探究(转)
出处: 链接:https://www.jianshu.com/p/a1cd61fa22da ThreadLocal原理回顾 ThreadLocal的原理:每个Thread内部维护着一个ThreadLo ...
- ThreadLocal内存泄漏
原创转载请注明出处:https://www.cnblogs.com/agilestyle/p/11421437.html 内存泄漏 内存泄漏是指不再使⽤的对象⽆法得到及时的回收,持续占⽤内存空间,从⽽ ...
- ThreadLocal内存泄漏需要注意的
前段时间在网上看到了一篇关于ThreadLocal内存泄漏的文章 于是个人也研究了下ThreadLocal 对象,其原理是: ThreadLocal 定义的变量值 会存储在当前线程的一个map集合中 ...
- Java并发编程笔记之ThreadLocal内存泄漏探究
使用 ThreadLocal 不当可能会导致内存泄露,是什么原因导致的内存泄漏呢? 我们首先看一个例子,代码如下: /** * Created by cong on 2018/7/14. */ pub ...
- springboot-23-aspectj日志记录及threadlocal内存泄漏
对于请求参数的处理和响应, 如果在代码中体现日志会显得很繁琐, 普遍的解决方案是使用spring的切面方案去解决. 这儿使用的是springboot的切面: http://www.cnblogs.co ...
随机推荐
- JAVA企业级应用TOMCAT实战(三)
JVM优化涉及到两大方面我个人的理解 .如何分配JVM的内存空间 .我应该使用什么垃圾回收器 JVM产生的垃圾需要回收.回收有不同的回收器. JVM的调优需要了解各个垃圾回收机制的原理. 终极目标:降 ...
- Codeforces Round #632 (Div. 2) 题解
空山新雨后,天气晚来秋. 明月松间照,清泉石上流. 竹喧归浣女,莲动下渔舟. 随意春芳歇,王孙自可留.--王维 A. Little Artem 网址:https://codeforces.com/co ...
- 编写管理IP地址参数脚本(永久性)
1.用各种命令取出/etc/passwd文件前5行的最后一个字母.(2种) 2.编写管理IP地址参数脚本(永久性) a.只能用sed命令完成 b.提示用户变量赋值(IP.子网掩码.网关.DNS等) c ...
- 正则表达式(grep,awk,sed)和通配符
1. 正则表达式 1. 什么是正则表达式? 正则表达式就是为了处理大量的字符串而定义的一套规则和方法. 通过定义的这些特殊符号的辅助,系统管理员就可以快速过滤,替换或输出需要的字符串. Linux正则 ...
- php数组存在重复的相反元素,去重复
$arr1=array('a_b','c_d','b_a','d_c'); $arr2=array('a_b','c_d','b_a','d_c'); 条件: a_b==b_a:c_d==d_c: 需 ...
- log4net进阶手札(二):基本用法
本节将主要在WebSite中,对保存日志在文本文件的基本用法来进行介绍,并结合WebForm的初始化方式区别进行说明,解决方案如下图所示: 一.WebSite应用第1步:配置Web.Config文件, ...
- DNS 处理模块 dnspython
简介: dnspython (http://www.dnspython.org/)是Python实现一个DNS的工具包,支持所有的记录类型,可以用于查询.传输并动态更新ZONE信息. 安装 wget ...
- 7) 项目准备流程 和 django权限六表
一.项目准备 1. 创建django项目 2. 创建数据库 —— init文件中声明mysql —— settings中配置数据库 import pymysql pymysql.install_as_ ...
- 正方形已知两点对角线求另外两点(POJ2002)
至于为什么,上图.转载于MZW_BG 枚举正方形的一条边,此时有上正方形和下正方形. 最后正方形个数/4,因为每个正方形被枚举了4条边 #include <bits/stdc++.h> u ...
- 洛谷p1149
一道很有意思的题目嘞. 这道题目看起来,用搜索似乎无疑了. 我想了这样一个办法(看了很多博客似乎都没用这种方法),可能是觉得太麻烦了吧: 1.我们先把0到9的数字排列,找出排列消耗火柴等于0的序列.这 ...