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 ...
随机推荐
- OSG加载倾斜摄影数据
目录 1. 概述 2. 实例 2.1. 代码 2.2. 解析 3. 结果 1. 概述 ContextCapture(Smart3D)生成的倾斜摄影模型数据一般都形如如下组织结构: 在Data目录下包含 ...
- Flutter自己实现一个ProgressHUD
用惯了iOS的SVProgressHUD,但是在flutter pub上的并没有找到类似的实现,于是自己实现一个 主要实现四个基本功能 Loading显示 成功显示 错误显示 进度显示:环形进度条和文 ...
- 在CentOS 7中安装配置JDK8
为什么80%的码农都做不了架构师?>>> ###说明 参考博客:http://blog.csdn.net/czmchen/article/details/41047187 系统环 ...
- MySQL数据库的套接字文件和pid文件
MySQL数据库的套接字文件和pid文件 socket文件:当用Unix域套接字方式进行连接时需要的文件. pid文件:MySQL实例的进程ID文件. MySQL表结构文件:用来存放MySQL表结构定 ...
- Excel中拆分列
常常在linux下我们写个shell,结果输出至txt中需要把数据一条一条的抠出来,也是很累人的事情,而直接输出值excel中的话相对较简单,但是会集中在第一列.这时候也不用担心,在Excel中选择第 ...
- Leetcode---Solutions&Notes
Leetcode已经成为面试必备技能之一,为了紧随潮流,也模仿大佬们刷刷题. 1.采用"龟系"做法,每道题尽量做到时间复杂度和空间复杂度的较优水平: 2.每道题的Solution先 ...
- ansible roles 自动化安装
例: ansible roles 自动化安装memcached 文件目录结构如下: cat memcached_role.yml - hosts: memcached remote_user: ro ...
- bat 命令
1.强制杀死进程 /F force 强制性/IM image + 进程名 TASKKILL /F /IM python.exe
- STL之traits编程技法
traits编程技法利用了“内嵌型别”的编程技巧与编译器的template参数推导功能. 下面主要看看利用traits编程技法实现的迭代器萃取机制. 5种迭代器类型定义: struct input_i ...
- Nginx入门资料
最近在学习Nginx,记录一下自己的学习历程. 1. Nginx开发从入门到精通 (淘宝技术团队编写,值得一看) 2. <深入理解Nginx:模块开发与架构解析> 3. Nginx模块开发 ...