您当前的位置:首页 > 电脑百科 > 程序开发 > 编程百科

来说说ThreadLocal内存溢出问题

时间:2021-06-17 11:14:07  来源:今日头条  作者:老顾聊技术

前言

上次有个小伙伴问我,说他面试的时候,被问到ThreadLocal内存溢出问题,没有回答出来;那我们今天就来了解一下ThreadLocal。

ThreadLocal介绍

多线程在访问同一个变量时会产生线程安全问题,ThreadLocal是JDK包提供的,它提供线程本地变量,如果创建一个ThreadLocal变量,那么访问这个变量的每个线程都会有这个变量的一个副本,在实际多线程操作的时候,操作的是自己本地内存中的变量,从而规避了线程安全问题,如下图所示

来说说ThreadLocal内存溢出问题

 

ThreadLocal使用

开启两个线程,在每个线程内部设置了本地变量的值,然后调用print方法打印当前本地变量的值。如果在打印之后调用本地变量的remove方法会删除本地内存中的变量,代码如下所示

来说说ThreadLocal内存溢出问题

 

执行结果

thread1 :localVar1
thread2 :localVar2
thread1 after remove : null
thread2 after remove : null

上面代码能够看出,虽然2个线程都使用了ThreadLocal localVar变量,但是线程里面的变量互相不影响。

ThreadLocal原理

我们来看看ThreadLocal是怎么实现的?我们来看一下源码

set源码

来说说ThreadLocal内存溢出问题

 

 在上面的代码中,(2)处调用getMap方法获得当前线程对应的threadLocals,该方法代码如下

ThreadLocalMap getMap(Thread t) {
    return t.threadLocals; //获取线程自己的变量threadLocals,并绑定到当前调用线程的成员变量threadLocals上
}

如果调用getMap方法返回值不为null,就直接将value值设置到threadLocals中(key为当前ThreadLocal引用,值为本地变量);如果getMap方法返回null说明是第一次调用set方法(前面说到过,threadLocals默认值为null,只有调用set方法的时候才会创建map),这个时候就需要调用createMap方法创建threadLocals,该方法如下所示

void createMap(Thread t, T firstValue) {
    t.threadLocals = new ThreadLocalMap(this, firstValue);
}

createMap方法不仅创建了threadLocals,同时也将要添加的本地变量值添加到了threadLocals中。

get源码

来说说ThreadLocal内存溢出问题

 

在get方法的实现中,首先获取当前调用者线程,如果当前线程的threadLocals不为null,就直接返回当前线程绑定的本地变量值,否则执行setInitialValue方法初始化threadLocals变量。在setInitialValue方法中,类似于set方法的实现,都是判断当前线程的threadLocals变量是否为null,是则添加本地变量(这个时候由于是初始化,所以添加的值为null),否则创建threadLocals变量,同样添加的值为null

remove实现

来说说ThreadLocal内存溢出问题

 

remove方法判断该当前线程对应的threadLocals变量是否为null,不为null就直接删除当前线程中指定的threadLocals变量

溢出分析

每个线程内部有一个名为threadLocals的成员变量该变量的类型为
ThreadLocal.ThreadLocalMap类型(类似于一个HashMap)
,其中的key为当前定义的ThreadLocal变量的this引用,value为我们使用set方法设置的值。每个线程的本地变量存放在自己的本地内存变量threadLocals中如果当前线程一直不消亡,那么这些本地变量就会一直存在(所以可能会导致内存溢出),因此使用完毕需要将其remove掉。

看下图:

来说说ThreadLocal内存溢出问题

 

番外篇

1、ThreadLocalMap 内部 Entry 中 key 使用的是对 ThreadLocal 对象的弱引用,这是为了避免内存泄露,因为如果是强引用,那么即使其他地方没有对 ThreadLocal 对象的引用,ThreadLocalMap 中的 ThreadLocal 对象还是不会被回收,而如果是弱引用则这时候 ThreadLocal引用是会被回收掉的

2、但是对于的 value 还是不能被回收,这时候 ThreadLocalMap 里面就会存在 key 为 null 但是 value 不为 null 的 entry 项,虽然 ThreadLocalMap 提供了 set,get,remove 方法在一些时机下会对这些 Entry 项进行清理,但是这是不及时的,也不是每次都会执行的,所以一些情况下还是会发生内存泄露,所以在使用完毕后即使调用 remove 方法才是解决内存泄露的最好办法。

3.线程池里面设置了 ThreadLocal 变量一定要记得及时清理,因为线程池里面的核心线程是一直存在的,如果不清理,那么线程池的核心线程的 threadLocals 变量一直会持有 ThreadLocal 变量。

总结

希望这篇文章能够帮助小伙伴们理解,这里再提供网上常用的图片,有助于小伙伴理解

来说说ThreadLocal内存溢出问题

 

谢谢!!!



Tags:ThreadLocal   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,如有任何标注错误或版权侵犯请与我们联系(Email:2595517585@qq.com),我们将及时更正、删除,谢谢。
▌相关推荐
前言上次有个小伙伴问我,说他面试的时候,被问到ThreadLocal内存溢出问题,没有回答出来;那我们今天就来了解一下ThreadLocal。ThreadLocal介绍多线程在访问同一个变量时会产生线...【详细内容】
2021-06-17  Tags: ThreadLocal  点击:(161)  评论:(0)  加入收藏
是什么ThreadLocal从名字上看好像是一个Thread,其实并不是,它是Therad的局部变量的维护类。作用是让变量私有化(为每个Thread提供变量的副本),以此来实现线程间变量的隔离。比如...【详细内容】
2021-01-14  Tags: ThreadLocal  点击:(188)  评论:(0)  加入收藏
当多线程访问共享可变数据时,涉及到线程间同步的问题,并不是所有时候,都要用到共享数据,所以就需要线程封闭出场了。数据都被封闭在各自的线程之中,就不需要同步,这种通过将数据封...【详细内容】
2020-07-29  Tags: ThreadLocal  点击:(44)  评论:(0)  加入收藏
闲谈ThreadLocal前面在我的GitHub仓库 V-LoggingTool 中有简单的使用过ThreadLocal,主要用在了切面类中,功能上需要取到前置增强拦截到的用户信息暂存,执行到后置增强时从该Thr...【详细内容】
2020-07-05  Tags: ThreadLocal  点击:(57)  评论:(0)  加入收藏
FastThreadLocal 作用与JDK 原生的ThreadLocal功能是一样的,FastThreadLocal 持有指定类的对象,可以保证每个线程都持有一个唯一实例,每个线程持有实例都只在本线程内使用,所以不会有并发问题。但它的访问速度更快,顾名思...【详细内容】
2019-08-28  Tags: ThreadLocal  点击:(314)  评论:(0)  加入收藏
▌简易百科推荐
摘 要 (OF作品展示)OF之前介绍了用python实现数据可视化、数据分析及一些小项目,但基本都是后端的知识。想要做一个好看的可视化大屏,我们还要学一些前端的知识(vue),网上有很多比...【详细内容】
2021-12-27  项目与数据管理    Tags:Vue   点击:(1)  评论:(0)  加入收藏
程序是如何被执行的  程序是如何被执行的?许多开发者可能也没法回答这个问题,大多数人更注重的是如何编写程序,却不会太注意编写好的程序是如何被运行,这并不是一个好...【详细内容】
2021-12-23  IT学习日记    Tags:程序   点击:(9)  评论:(0)  加入收藏
阅读收获✔️1. 了解单点登录实现原理✔️2. 掌握快速使用xxl-sso接入单点登录功能一、早期的多系统登录解决方案 单系统登录解决方案的核心是cookie,cookie携带会话id在浏览器...【详细内容】
2021-12-23  程序yuan    Tags:单点登录(   点击:(8)  评论:(0)  加入收藏
下载Eclipse RCP IDE如果你电脑上还没有安装Eclipse,那么请到这里下载对应版本的软件进行安装。具体的安装步骤就不在这赘述了。创建第一个标准Eclipse RCP应用(总共分为六步)1...【详细内容】
2021-12-22  阿福ChrisYuan    Tags:RCP应用   点击:(7)  评论:(0)  加入收藏
今天想简单聊一聊 Token 的 Value Capture,就是币的价值问题。首先说明啊,这个话题包含的内容非常之光,Token 的经济学设计也可以包含诸多问题,所以几乎不可能把这个问题说的清...【详细内容】
2021-12-21  唐少华TSH    Tags:Token   点击:(9)  评论:(0)  加入收藏
实现效果:假如有10条数据,分组展示,默认在当前页面展示4个,点击换一批,从第5个开始继续展示,到最后一组,再重新返回到第一组 data() { return { qList: [], //处理后...【详细内容】
2021-12-17  Mason程    Tags:VUE   点击:(14)  评论:(0)  加入收藏
什么是性能调优?(what) 为什么需要性能调优?(why) 什么时候需要性能调优?(when) 什么地方需要性能调优?(where) 什么时候来进行性能调优?(who) 怎么样进行性能调优?(How) 硬件配...【详细内容】
2021-12-16  软件测试小p    Tags:性能调优   点击:(19)  评论:(0)  加入收藏
Tasker 是一款适用于 Android 设备的高级自动化应用,它可以通过脚本让重复性的操作自动运行,提高效率。 不知道从哪里听说的抖音 app 会导致 OLED 屏幕烧屏。于是就现学现卖,自...【详细内容】
2021-12-15  ITBang    Tags:抖音防烧屏   点击:(23)  评论:(0)  加入收藏
11 月 23 日,Rust Moderation Team(审核团队)在 GitHub 上发布了辞职公告,即刻生效。根据公告,审核团队集体辞职是为了抗议 Rust 核心团队(Core team)在执行社区行为准则和标准上...【详细内容】
2021-12-15  InfoQ    Tags:Rust   点击:(24)  评论:(0)  加入收藏
一个项目的大部分API,测试用例在参数和参数值等信息会有很多相似的地方。我们可以复制API,复制用例来快速生成,然后做细微调整既可以满足我们的测试需求1.复制API:在菜单发布单...【详细内容】
2021-12-14  AutoMeter    Tags:AutoMeter   点击:(20)  评论:(0)  加入收藏
最新更新
栏目热门
栏目头条