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 ...
随机推荐
- nginx 配置大吞吐量
ng做反向代理服务是如果没有这两行配置吞吐量到8000-10000就上不去. proxy_http_version 1.1; # 后端配置支持HTTP1.1,必须配 proxy_set_header ...
- python学习23之标准库
'''''''''标准库1.datetime 日期时间模块存在于Lib/datetime.py文件内'''from datetime import datetime,date,time #from d ...
- [Inno Setup] 退出安装程序的两种方式
1. 完全静默的退出 procedure ExitProcess(exitCode:integer); external 'ExitProcess@kernel32.dll stdcall'; ... ...
- 使用VSCode连接到IBM Cloud区块链网络
文章目录 从IBM Cloud控制面板导出连接信息 在VSCode中创建gateway和wallet 在VSCode中提交transaction 上篇文章我们讲到怎么在IBM Cloud搭建区块链环境 ...
- JAVA 之 EL表达式
一.什么是EL表达式 1.Expression Language表达式语言 2.是一种在JSP页面获取数据的简单方式(只能获取数据,不能设置数据) 语法格式:${expression } 二.EL中的 ...
- 如何迅速分析出系统CPU的瓶颈在哪里?
内容出自极客时间专栏<Linux 性能优化实战> CPU 的性能指标那么多,CPU 性能分析工具一抓一大把,换成实际的工作场景,该观察什么指标.选择哪个性能工具呢? 不要担心,今天我就以多 ...
- 在服务器本地监控服务端口命令之ss
在服务器本地监控服务端口命令之ss 当服务器的socket连接数量变得非常大时,无论是使用netstat命令还是直接cat /proc/net/tcp,执行速度都会很慢.可能你不会有 切身的感受,但当 ...
- 杭电的题,输出格式卡的很严。HDU 1716 排列2
题很简单,一开始写代码,是用整数的格式写的,怎么跑都不对,就以为算法错了,去看大佬们的算法STL全排列:next_permutation(); 又双叒叕写了好几遍,PE了将近次,直到跑了大佬代码发现, ...
- 数学--数论-- AtCoder Beginner Contest 151(组合数+数学推导)好题(๑•̀ㅂ•́)و✧
思路统计最大值出现的次数,和最小值出现的次数.虽然是每次都是MAX-MIN,我们先求MAX的和,然后再求MIN的和,做差. 这次代码写的真的很漂亮 题目地址: #include <bits/st ...
- [CodeForces-259C] Little Elephant and Bits
C. Little Elephant and Bits time limit per test 2 seconds memory limit per test 256 megabytes input ...