最新要闻
- 焦点热文:小米13 Pro把单反相机技术塞入手机里!雷军:效果惊艳
- AMD三颗新U齐发!锐龙9 7900、锐龙7 7700、锐龙5 7600图赏
- 暴雪国服代理谈判被曝进入"二选一"阶段:手游版权开发分成是核心
- 报道:SpaceX猎鹰重型火箭再次发射美军卫星:能抗核打击
- 苹果中国官网上线智能家居板块:一个LED灯泡卖168元 贵吗?
- 世界实时:《三体》电视剧过审上微博热搜 网友:只求别魔改!
- 环球今日报丨去意已决?巴菲特再度减持比亚迪
- 全球快消息!真爱粉!苏州加油为抢一加11首发跑到上海:对新品非常期待
- 全球即时看!又一豪华巨头败走中国 官网关停!长安终于可以独享车标了
- 环球新消息丨广告又来?Win11将在文件管理器显示“推荐内容”
- AMD锐龙7000新U不讲武德:编号更高 频率反而更低
- 车企"英文+数字"的新车命名规则被吐槽无趣 不如中文
- 外星人M18首发!京东方推出18英寸480Hz笔记本屏
- 前沿热点:抖音2023年春节红包来了:分4亿 最高可得万元奖金
- 环球快看点丨彻底终结充电焦虑?韩国SK On新技术:汽车电池18分钟充满
- 世界微资讯!电竞手机要消亡!卢伟冰:有了Redmi K60就不需要电竞手机
手机
iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?
警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案
- iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?
- 警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案
- 男子被关545天申国赔:获赔18万多 驳回精神抚慰金
- 3天内26名本土感染者,辽宁确诊人数已超安徽
- 广西柳州一男子因纠纷杀害三人后自首
- 洱海坠机4名机组人员被批准为烈士 数千干部群众悼念
家电
ThreadLocal底层原理
文章目录
- 1.什么是ThreadLocal?
- 2.ThreadLocal基本用法
- 3.ThreadLocal的应用场景
- 4.ThreadLocal底层原理
- 5.强软弱引用之间的区别
- 5.1强引用
- 5.2软引用
- 5.3弱引用
- 5.4虚引用
- 6.ThreadLocal内存泄漏问题
- 7.如何防止ThreadLocal内存泄漏问题
- 8.ThreadLocal采用的是弱引用
1.什么是ThreadLocal?
ThreadLocal提供了线程本地变量,它可以保证访问到的变量属于当前线程,每个线程都保存有一个变量副本,每个线程的变量都不同。ThreadLocal相当于提供了一种线程隔离,将变量与线程相绑定。ThreadLocal适用于在多线程情况下,可以实现传递数据,实现线程隔离。
(资料图片仅供参考)
2.ThreadLocal基本用法
可以创建一个TheadLocal的对象然后set是设置内容,get是获取内容。可以做到线程之间变量的隔离。
public static void main(String[] args) { ThreadLocal stringThreadLocal = new ThreadLocal<>(); stringThreadLocal.set("wjz nb"); new Thread(() -> { stringThreadLocal.set("wjz mvp"); System.out.println("子线程:" + stringThreadLocal.get()); }).start(); System.out.println("主线程:"+stringThreadLocal.get()); }
我们可以开一个主线程在主线程中将ThreadLocal设置为"wjz nb",然后再开一个子线程在子线程中设置stringThreadLocal值为"wjz mvp",然后我们执行这段程序。看看结果如果主线程和子线程的值不同说明ThreadLocal确实隔离了,如果他们两个的值相同说明没隔离。
结果显示他俩确实是隔离的。
3.ThreadLocal的应用场景
设计模式中的模板方法,他会把一些公有的东西放在模板类类,其他方法交给子类来实现,那么就可以把一些变量缓存在一个模板类当中这样我的子类就可以去获取。
SpringMVC获取HttpRequest,首先tomcat接受请求,创建一个线程然后通过Servlet处理请求,SpringMVC对Servlet进行了一层封装,封装了HttpRequest对象放入当前的ThreadLocal然后再通过Aop拦截请求,然后在控制器层的ThreadLocal获取到该HttpRequest。虽然经过了重重处理,但是最终还是在同一个线程里。
比如说下面这段代码我想要获取HttpServletRequest对象,是通过RequestContextHolder获取的我们来看一下这个类里面是啥样的
我们可以看到这里面定义了ThreadLocal专门缓存HttpServletRequest对象,然后我们就可以在控制层通过ThreadLocal获取该线程的HttpServletRequest对象
AOP拦截请求,在Aop层缓存一个变量到ThreadLocal中,然后我们可以在控制层拿到这个变量。
4.ThreadLocal底层原理(点击参考ThreadLocal详细源码分析)
TheadLocal是通过ThreadLocalMap存放的,ThreadLocalMap中可以存放多个不同的ThreadLocal对象,同一个线程可以通过ThreadLocalMap存放多个ThreadLocal对象。每个ThreadLocal对象只能缓存一个变量值。底层的ThreadLocalMap
public T get() { Thread t = Thread.currentThread(); ThreadLocalMap map = getMap(t); if (map != null) { ThreadLocalMap.Entry e = map.getEntry(this); if (e != null) { @SuppressWarnings("unchecked") T result = (T)e.value; return result; } } return setInitialValue(); }
我们可以看到首先拿到该线程的ThreadLocalMap,然后通过这个map.getEntry里面传入this即当前的ThreadLocal我们能获取到value值。
5.强软弱引用之间的区别
5.1强引用
当内存不足时,JVM开始进行GC,对于强引用对象,就算是出现了OOM也不会对该对象进行回收,死都不会回收。
如图所示就算堆内存不够了,抛异常也不会回收,这就是强引用。
5.2软引用
当系统内存充足的时候,不会被回收,当系统内存不足时,它会被回收,比如高速缓存就用到过软引用,内存够用时就保留,不够时就回收。下面我们来看一个例子
public static void main(String[] args) { Object o1 = new Object(); SoftReference
首先我创建一个强引用对象o1,然后再把它设置成软引用,然后将o1置为null,打印o1被置为null前后的对象情况。
这是在内存充足的情况下,在o1不为null的情况下,o1强引用对象和软引用对象是一样的,o1被置为null之后,程序结束之前执行finally里面的代码,o1已经是null,所以o1为null,但是软引用没有被回收。
当我们设置一下JVM的参数,然后我把当前堆内存最大空间为5M,
然后突然申请bits一共30M,那肯定不够了,然后再运行看一下结果
我们可以看到当内存不足时软引用也被回收了。
5.3弱引用
public class WeakReferenceDemo { public static void main(String[] args) { Object o1 = new Object(); WeakReference
弱引用就是这样,内存空间足够的情况下只要发生GC他也会被回收。
5.4虚引用
虚引用对象,在收集器确定其引用对象可能被回收后排队。虚引用最常用于以比Java终结机制更灵活的方式安排死前清理操作,如果垃圾收集器在某个时间点确定虚引用的对象是可达的,则在该时间或稍后某个时间,它将使引用入队。他的构造器得参数就有这样的一个队列。
public PhantomReference(T referent, ReferenceQueue super T> q) { super(referent, q); }
虚引用的get方法始终返回空。所以一般情况下虚引用没啥大用。为对象生成虚引用关联的唯一目的就是能在这个对象被收集器回收时收到一个系统通知。jdk中的直接内存回收就用到了虚引用,因为直接内存不在jvm管理范围,所以会在堆内存中分配一个对象保存这个堆外内存的引用,这个就是虚引用,一旦这个对象被回收,相应的用户线程就会收到通知并对直接内存进行清理工作。
6.ThreadLocal内存泄漏问题
内存泄漏就是我们申请了内存,但是该内存一直不会被释放。内存溢出就是申请内存,但是实际的内存不足,就是你管你妈要钱,但是你妈没钱。然后我们通过一段小demo描述一下ThreadLocal内存泄漏的问题。
public static void main(String[] args) { ThreadLocal stringThreadLocal1 = new ThreadLocal<>(); stringThreadLocal1.set("wjz"); stringThreadLocal1 = null; Thread thread = Thread.currentThread(); System.out.println(thread); }
我们先为这个stringThreadLocal设置一个值,然后再把这个置为null,然后打断点看看这个线程里还有没有这个ThreadLocal。
我们可以来分析一下原因
如图所示每个线程中有自己独立的ThreadLocalMap,ThreadLocalMap底层基于Entry对象封装,Entry key=ThreadLocal堆内存空间内存地址指向,Entry key=使用弱引用的方式指向ThreadLocal堆内存地址 如果没有发生GC回收的情况下该对象不会被清除,即便发生gc,该ThreadLocal对象被清除,但是Entry对象也不会被清除,此时Entry对象中的key=null,value还会在。
7.如何防止ThreadLocal内存泄漏问题
1.ThreadLocal已经为我们封装好了一个remove方法,这个方法可以直接移除ThreadLocalMap中Entry数组中的Entry对象
public static void main(String[] args) { ThreadLocal stringThreadLocal1 = new ThreadLocal<>(); stringThreadLocal1.set("wjz"); // 移除ThreadLocalMap中Entry数组中的Entry对象 stringThreadLocal1.remove(); //stringThreadLocal1与堆内存中的ThreadLocal断开引用 stringThreadLocal1 = null; Thread thread = Thread.currentThread(); System.out.println(thread); }
看一下结果
刚才10号位置存储了我们输入的字符串现在10号位置没了,说明内存泄漏的问题已经解决。然后我们再点进去看一下remove方法。
public void remove() { ThreadLocalMap m = getMap(Thread.currentThread()); if (m != null) m.remove(this); }
我们先拿到当前线程对应的ThreadLocalMap如果这个map不为空的话就删除this(ThreadLocal对象),就是切断ThreadLocalMap对堆内存的引用。
2.ThreadLocal在每次set执行的时候会判断一下key是不是为空如果为空他会替换“陈旧的”Entry。
private void set(ThreadLocal> key, Object value) { // We don"t use a fast path as with get() because it is at // least as common to use set() to create new entries as // it is to replace existing ones, in which case, a fast // path would fail more often than not. Entry[] tab = table; int len = tab.length; int i = key.threadLocalHashCode & (len-1); for (Entry e = tab[i]; e != null; e = tab[i = nextIndex(i, len)]) { ThreadLocal> k = e.get(); if (k == key) { e.value = value; return; } if (k == null) { replaceStaleEntry(key, value, i); return; } }
如果key为空他会走进这个方法replaceStaleEntry。
// If key not found, put new entry in stale slot tab[staleSlot].value = null; tab[staleSlot] = new Entry(key, value);
如果key不存在,他就会在旧的槽上添加一个新的entry。综上所述ThreadLocal对象在不用的时候一定要调用一下remove()方法。
ThreadLocal底层原理
焦点热文:小米13 Pro把单反相机技术塞入手机里!雷军:效果惊艳
AMD三颗新U齐发!锐龙9 7900、锐龙7 7700、锐龙5 7600图赏
暴雪国服代理谈判被曝进入"二选一"阶段:手游版权开发分成是核心
报道:SpaceX猎鹰重型火箭再次发射美军卫星:能抗核打击
环球今热点:在QEMU-KVM环境下部署Oracle 19.16 RAC
全球要闻:HTML超文本标记语言3
苹果中国官网上线智能家居板块:一个LED灯泡卖168元 贵吗?
世界实时:《三体》电视剧过审上微博热搜 网友:只求别魔改!
环球今日报丨去意已决?巴菲特再度减持比亚迪
全球快消息!真爱粉!苏州加油为抢一加11首发跑到上海:对新品非常期待
世界观速讯丨C++引用【cherno课程学习】
【天天报资讯】「年终总结」写了 3 年文章的我,昨天第一次露脸直播。
环球今日报丨【前端调试】- 利用 Performance 和 Memory 分析内存
热点!操作系统 — 精髓与设计原理(第一章 计算机系统概述)
世界播报:学习笔记——Mybatis映射文件根标签与子标签
全球即时看!又一豪华巨头败走中国 官网关停!长安终于可以独享车标了
环球新消息丨广告又来?Win11将在文件管理器显示“推荐内容”
AMD锐龙7000新U不讲武德:编号更高 频率反而更低
车企"英文+数字"的新车命名规则被吐槽无趣 不如中文
外星人M18首发!京东方推出18英寸480Hz笔记本屏
全球热议:java不同版本jdk切换
每日焦点!读博初始心境-求讨论
前沿热点:抖音2023年春节红包来了:分4亿 最高可得万元奖金
环球快看点丨彻底终结充电焦虑?韩国SK On新技术:汽车电池18分钟充满
世界微资讯!电竞手机要消亡!卢伟冰:有了Redmi K60就不需要电竞手机
国内演员指责电视收费乱象:大几千买的电视看不了 打开全要收费
NAT类型检测方案
世界热议:学习笔记——Mybatis核心配置文件概述及根标签
VisualStudio 使用 FastTunnel 辅助搭建远程调试环境
世界观焦点:“外星科技”加持!Redmi 12C支持双SIM卡+TF卡拓展:699元起
搜狐张朝阳谈工作意义:年轻人赚钱享乐的想法不对
同步小米13 Ultra!小米平板6/6 Pro来了:处理器、屏幕大升级
今晚20点整:京东年货红包重磅加码 最高9999元
360Hz超高刷也白菜价了 泰坦军团1ms电竞显示器到手1629元
火山引擎 DataTester:5 个优化思路,构建高性能 A/B 实验平台
环球新资讯:对话阿里云叔同:如何看待 2022 年云原生的发展,2023 年有哪些值得关注的技术?
全球新动态:字符串匹配算法综述
新资讯:网易云音乐用户画像资产治理及业务赋能
每日热议![概率论与数理统计]笔记:3.1 随机向量的分布
环球短讯!俄罗斯开发者1年拿不到钱!好好的微星AfterBurner被一场战争害死
盘点CES上让人耳目一新的小玩意:极具创意
参与美国“阿尔忒弥斯计划” 日本人将首次登陆月球:日期未定
2499元起 Redmi K60成了:京东好评率比iPhone 14更高
新动态:你能接受不?奔驰Smart精灵#1开启硬件订阅:座椅加热1299元
环球播报:软件开发入门教程网之C++ 引用
[笔记]斜率优化
HTML超文本标记语言2
时讯:股价暴跌后!特斯拉最大华裔散户天天“炮轰”马斯克
环球今热点:手慢真无了 码已不全!森马羽绒/棉服大促:一百多到手
世界热讯:美菱推出“杀新冠冰箱”:灭杀率高达99.9% 已过权威认证
全球时讯:PS5主机应该横放还是竖放引热议 索尼:都可以
热点评!配第四代i-MMD 东风本田新款英仕派e:HEV官图发布:真大号思域
世界视点!【操作系统实验/Golang】实验4:虚拟内存页面置换算法
世界时讯:Python工具箱系列(二十二)
初识Vue
环球消息!ACWING 4261. 孤独的照片
外观复刻iPhone 14 Pro!乐视手机S1 Pro标配8+128GB存储:自称5G小霸王
当前讯息:一加8钉子户上车一加11:真正上手那一刻被惊艳到了
每日消息!一加11成为最火爆的第二代骁龙8旗舰!李杰:友商都可以去查
NVIDIA推出第5代MAX-Q技术:游戏本性能进一步提升
女子买200万豪车 亲友400箱礼花庆贺 整条街道都摆满了
当前热议!无监控,不运维!深入浅出介绍ChengYing监控设计和使用
学习笔记——在IDEA中创建Maven版的web工程;框架;Mybatis简介;搭建Mybatis框架步骤
每日热议!成功率100%!中国民营火箭谷神星一号五连胜:一箭五星
今日热闻!33岁男子酗酒20年骨头坏死:13岁开始喝、每天至少半斤
动画版口碑崩盘 《三体》国产剧版过审获许可证 最快本月上线腾讯视频
世界速递!特斯拉最大散户投资者成马斯克头号反对者:连续多日公开炮轰
关注:一步一步实现若依框架--2.2实现后台限流rate_limiter
最资讯丨ACWING 4645. 选数异或
天天要闻:全球第四大汽车制造商CEO:欧洲中产阶级将选购中国汽车
清华应届硕士炮轰字节恶意低薪:月薪2万 硕士白读还倒贴
世界快看:面试官:数据库日期类型字段,需要兼容不同数据库,应该如何选择?
今日最新!ThreadLocal源码解析及实战应用
交换机二层组播配置
管理工具造成的阻塞
前沿热点:国产战机大片!电影《长空之王》定档:今年五一上映
杭州外来人口占3成 河南人数比肩本地土著 原来有历史原因
小米13系列大卖、汽车售价可达35万以上 小米高端成了:股价大涨
采埃孚新安全带:不用开空调 可提升电动车15%续航
焦点速读:3999元起 一加11首销51分钟打破所有二代骁龙8销量、销售额双记录
家用光纤宽带多少兆合适?家用光纤怎么接路由器?
招财猫的原型是什么猫?招财猫左手右手分别代表什么?
修正液的成分是什么?修正液的性质有哪些?
丁克家族是什么意思?丁克家庭的好处和坏处有哪些?
纪宝贝是什么电视剧的角色?纪宝贝是什么品种的狗?
印度首家旗舰店来了?传苹果(AAPL.US)开始招聘零售店员工
年终盘点丨最受开发者欢迎的文章 TOP20
天天快报!华硕ROG首款DP2.1接口显示器发布:无压缩4K 160Hz画质
世界热讯:车主激烈维权上演0元购!特斯拉成都门店否认:都是理性维权
重达2.4吨!美国40年前发射卫星今日坠落地球:或为朝鲜半岛
行业最低!一加Buds Pro 2首销899元:全链路延时仅54ms
【全球独家】腾讯发布未成年人春节寒假限玩通知:春节7天全开 工作日继续禁玩
京音平台-一起玩转SCRM之电销系统
全球滚动:特斯拉降价 国外车主怎么就不闹:原因发人深思
环球观速讯丨电视“套娃式充会员”吃相难看 有人呼吁建立互相兼容的会员体系
天天要闻:电子后视镜正式获批!吉利路特斯首批上车:选装费1万6
北斗三号卫星系统总设计师:北斗核心指标已超GPS
精选!极端暖冬席卷欧洲 多国冬天“入夏”:天然气价格也遭暴跌
环球热门:深拷贝、浅拷贝