ThreadLocal为什么会内存泄漏
1、首先看下ThreadLocal的原理图:
在ThreadLocal的生命周期中,都存在这些引用。
其中,实线代表强引用,虚线代表弱引用;
2、ThreadLocal的实现:每个Thread维护一个ThreadLocalMap映射表,这个映射表的key是ThreadLocal实例本身,value是真正需要存储的Object;
3、也就是说ThreadLocal本身不存储值,它只是作为一个key来让线程从ThreadLocalMap获取value,值得注意的是图中的虚线,表示ThreadLocalMap是使用ThreadLocal的弱引用作为key,其在GC时会被回收;
4、ThreadLocalMap使用ThreadLocal的弱引用作为key,如果一个ThreadLocal没有外部强引用来引用它,那么系统 GC 的时候,这个ThreadLocal势必会被回收,这样一来,ThreadLocalMap中就会出现key为null的Entry,就没有办法访问这些key为null的Entry的value,如果当前线程再迟迟不结束的话,这些key为null的Entry的value就会一直存在一条强引用链:Thread Ref -> Thread -> ThreaLocalMap -> Entry -> value永远无法回收,造成内存泄漏。
5、总的来说就是,ThreadLocal里面使用了一个存在弱引用的map, map的类型是ThreadLocal.ThreadLocalMap. Map中的key为一个threadlocal实例。这个Map的确使用了弱引用,不过弱引用只是针对key。每个key都弱引用指向threadlocal。 当把threadlocal实例置为null以后,没有任何强引用指向threadlocal实例,所以threadlocal将会被gc回收。
但是,我们的value却不能回收,而这块value永远不会被访问到了,所以存在着内存泄露。因为存在一条从current thread连接过来的强引用。只有当前thread结束以后,current thread就不会存在栈中,强引用断开,Current Thread、Map value将全部被GC回收。最好的做法是将调用threadlocal的remove方法,这也是等会后边要说的。
6、其实,ThreadLocalMap的设计中已经考虑到这种情况,也加上了一些防护措施:在ThreadLocal的get(),set(),remove()的时候都会清除线程ThreadLocalMap里所有key为null的value。这一点在上一节中也讲到过!
7、但是这些被动的预防措施并不能保证不会内存泄漏:
a、使用static的ThreadLocal,延长ThreadLocal的生命周期,可能导致内存泄漏;
b、分配只用了ThreadLocal又不再调用get()、set()、remove()方法,那么可能导致内存泄漏,因为这块内存会一直存在;
以下是源码:
/**
* The entries in this hash map extend WeakReference, using
* its main ref field as the key (which is always a
* ThreadLocal object). Note that null keys (i.e. entry.get()
* == null) mean that the key is no longer referenced, so the
* entry can be expunged from table. Such entries are referred to
* as "stale entries" in the code that follows.
*/
static class Entry extends WeakReference<ThreadLocal<?>> {
/** The value associated with this ThreadLocal. */
Object value;
Entry(ThreadLocal<?> k, Object v) {
super(k);
value = v;
}
}
ThreadLocal为什么会内存泄漏的更多相关文章
- 深入分析 ThreadLocal 内存泄漏问题
前言 ThreadLocal 的作用是提供线程内的局部变量,这种变量在线程的生命周期内起作用,减少同一个线程内多个函数或者组件之间一些公共变量的传递的复杂度.但是如果滥用ThreadLocal,就可能 ...
- 并发编程(四):ThreadLocal从源码分析总结到内存泄漏
一.目录 1.ThreadLocal是什么?有什么用? 2.ThreadLocal源码简要总结? 3.ThreadLocal为什么会导致内存泄漏? 二.ThreadLoc ...
- ThreadLocal以及内存泄漏
ThreadLocal是什么 ThreadLocal 的作用是提供线程内的局部变量,这种变量在线程的生命周期内起作用,减少同一个线程内多个函数或者组件之间一些公共变量的传递的复杂度.但是如果滥用Thr ...
- 分析 ThreadLocal 内存泄漏问题
ThreadLocal 的作用是提供线程内的局部变量,这种变量在线程的生命周期内起作用,减少同一个线程内多个函数或者组件之间一些公共变量的传递的复杂度.但是如果滥用 ThreadLocal,就可能会导 ...
- java多线程--------深入分析 ThreadLocal 内存泄漏问题
前言 ThreadLocal 的作用是提供线程内的局部变量,这种变量在线程的生命周期内起作用,减少同一个线程内多个函数或者组件之间一些公共变量的传递的复杂度.但是如果滥用ThreadLocal,就可能 ...
- 18.一篇文章,从源码深入详解ThreadLocal内存泄漏问题
1. 造成内存泄漏的原因? threadLocal是为了解决对象不能被多线程共享访问的问题,通过threadLocal.set方法将对象实例保存在每个线程自己所拥有的threadLocalMap中,这 ...
- ThreadLocal内存泄漏真因探究(转)
出处: 链接:https://www.jianshu.com/p/a1cd61fa22da ThreadLocal原理回顾 ThreadLocal的原理:每个Thread内部维护着一个ThreadLo ...
- 深入解析ThreadLocal 详解、实现原理、使用场景方法以及内存泄漏防范 多线程中篇(十七)
简介 从名称看,ThreadLocal 也就是thread和local的组合,也就是一个thread有一个local的变量副本 ThreadLocal提供了线程的本地副本,也就是说每个线程将会拥有一个 ...
- Java并发编程笔记之ThreadLocal内存泄漏探究
使用 ThreadLocal 不当可能会导致内存泄露,是什么原因导致的内存泄漏呢? 我们首先看一个例子,代码如下: /** * Created by cong on 2018/7/14. */ pub ...
随机推荐
- C++ 洛谷 P2458 [SDOI2006]保安站岗 from_树形DP
P2458 [SDOI2006]保安站岗 没学树形DP的,看一下. 题目大意:一棵树有N个节点,现在需要将所有节点都看守住,如果我们选择了节点i,那么节点i本身,节点i的父亲和儿子都会被看守住. 每个 ...
- HTTP 学习笔记03
通用信息头 Cache-Control : no-cache(不缓存当前请求) [*] Connection:close(返回当前请求后立即断开)[*] Date:...(HTTP消息产生的时间) P ...
- JDK源码阅读(三):ArraryList源码解析
今天来看一下ArrayList的源码 目录 介绍 继承结构 属性 构造方法 add方法 remove方法 修改方法 获取元素 size()方法 isEmpty方法 clear方法 循环数组 1.介绍 ...
- springMVC java.lang.IllegalStateException: getOutputStream() has already bee
在导出文件的时候,一直报这个错误. 网上一般的做法是out.clear();或者使用servlet或者Action返回null. 试过了这些方法都不成功. 最后直到试了在jsp重定向的方法才成功了. ...
- 修改SearchBar的取消按钮Cancel为中文
一开始在网上看到很多方法都是循环,好吧,我也循环 创建UISearchBar的时候循环,不行 用searchBarTextDidBeginEditing事件去循环,也不行 无语了,搜索了Baidu第一 ...
- 2.秋招复习简单整理之String、StringBuffer、StringBuilder的区别和联系
String特点: 1.String是不可变对象,一旦赋值创建就不变,这意味着对String的一切修改将产生一个新的字符串,比如String的subString,replace.toUpperCase ...
- 浅入深出Vue:注册
基本布局已经有了, 现在我们来开始做我们的注册页面~ 当然需要注册才能发表文章啊(糟老头子坏得很, 我可以只有我一个人能发啊). 这里我们设定只有注册才能发表文章,也就淡化了管理员这个概念.在开发中先 ...
- Docker学习第二天
CentOS 系列安装 Docker Docker 支持 CentOS6 及以后的版本. CentOS6 对于 CentOS6,可以使用 EPEL 库安装 Docker,命令如下 [root@MSJT ...
- python笔记(2)--字符串
一.字符串 字符串是不可变序列,具有序列的公共操作方法,具体操作见python笔记(1)--序列(列表 元组 range) 1.创建字符串 单引号:'Hello , I am Logan ! ' 双引 ...
- Spring+MyBatis时Access denied for user '高欢欢'@'localhost' (using password: YES)的异常解决方案
今天在做spring+mybatis整合的时候系统只要一运行就会报下面的错误,搞了几个小时硬是没有找的原因 警告: com.mchange.v2.resourcepool.BasicResourceP ...