线程隔离:每个线程有自己的 ThreadLocalMap 副本

一、核心原理
1. 数据存储结构
// 每个 Thread 对象内部都有一个 ThreadLocalMap
ThreadLocal.ThreadLocalMap threadLocals = null;

// ThreadLocalMap 内部使用 Entry 数组,Entry 继承自 WeakReference<ThreadLocal<?>>
static class Entry extends WeakReference<ThreadLocal<?>> {
Object value;
Entry(ThreadLocal<?> k, Object v) {
super(k); // 弱引用指向 ThreadLocal 实例
value = v; // 强引用指向实际存储的值
}
}
AI写代码

2. 关键设计
线程隔离:每个线程有自己的 ThreadLocalMap 副本
哈希表结构:使用开放地址法解决哈希冲突
弱引用键:Entry 的 key(ThreadLocal 实例)是弱引用
延迟清理:set / get 时自动清理过期条目
二、源码分析
1. set() 方法流程
public void set(T value) {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null) {
map.set(this, value); // this指当前ThreadLocal实例
} else {
createMap(t, value);
}
}

ThreadLocal 是强大的线程隔离工具,但需要谨慎使用。在 Web 应用和线程池场景中,必须在 finally 块中调用 remove(),这是避免内存泄漏的关键。

面试回答
关于 ThreadLocal,我从原理、场景和内存泄漏三个方面来说一下我的理解。

1. 首先,它的核心原理是什么?
简单来说,ThreadLocal 是一个线程级别的变量隔离工具。它的设计目标就是让同一个变量,在不同的线程里有自己独立的副本,互不干扰。

底层结构:每个线程(Thread对象)内部都有一个自己的 ThreadLocalMap(你可以把它想象成一个线程私有的、简易版的HashMap)。
怎么存:当我们调用 ThreadLocal.set(value) 时,实际上是以当前的 ThreadLocal 实例自身作为 Key,要保存的值作为 Value,存入当前线程的那个 ThreadLocalMap 里。
怎么取:调用 ThreadLocal.get() 时,也是用自己作为 Key,去当前线程的 Map 里查找对应的 Value。
打个比方:就像去银行租保险箱。Thread 是银行,ThreadLocalMap 是银行里的一排保险箱,ThreadLocal 实例就是你手里那把特定的钥匙。你用这把钥匙(ThreadLocal实例)只能打开属于你的那个格子(当前线程的Map),存取自己的东西(Value),完全看不到别人格子的东西。不同的人(线程)即使用同一款钥匙(同一个ThreadLocal实例),打开的也是不同银行的格子,东西自然隔离了。
2. 其次,它的典型使用场景有哪些?
正是因为这种线程隔离的特性,它特别适合用来传递一些需要在线程整个生命周期内、多个方法间共享,但又不能(或不想)通过方法参数显式传递的数据。最常见的有两个场景:

场景一:保存上下文信息(最经典)
比如在 Web 应用 或 RPC 框架 中处理一个用户请求时,这个请求从进入系统到返回响应,全程可能由同一个线程处理。我们会把一些信息(比如用户ID、交易ID、语言环境)存到一个 ThreadLocal 里。这样,后续的任何业务方法、工具类,只要在同一个线程里,就能直接 get() 到这些信息,避免了在每一个方法签名上都加上这些参数,代码会简洁很多。
场景二:管理线程安全的独享资源
典型例子是 数据库连接 和 SimpleDateFormat。
像 SimpleDateFormat 这个类,它不是线程安全的。如果做成全局共享,就要加锁,性能差。用 ThreadLocal 的话,每个线程都拥有自己的一个 SimpleDateFormat 实例,既避免了线程安全问题,又因为线程复用了这个实例,减少了创建对象的开销。
类似的,在一些需要保证数据库连接线程隔离(比如事务管理)的场景,也会用到 ThreadLocal 来存放当前线程的连接。
3. 最后,关于它的内存泄漏问题
ThreadLocal 如果使用不当,确实可能导致内存泄漏。它的根源在于 ThreadLocalMap 中 Entry 的设计。

问题根源:
ThreadLocalMap 的 Key(也就是 ThreadLocal 实例)是一个 弱引用。这意味着,如果外界没有强引用指向这个 ThreadLocal 对象(比如我们把 ThreadLocal 变量设为了 null),下次垃圾回收时,这个 Key 就会被回收掉,于是 Map 里就出现了一个 Key 为 null,但 Value 依然存在的 Entry。
这个 Value 是一个强引用,只要线程还活着(比如用的是线程池,线程会复用,一直不结束),这个 Value 对象就永远无法被回收,造成了内存泄漏。
如何避免:
良好习惯:每次使用完 ThreadLocal 后,一定要手动调用 remove() 方法。这不仅是清理当前值,更重要的是它会清理掉整个 Entry,这是最有效、最安全的做法。

https://www.zhihu.com/zvideo/1993097681883637449
https://www.zhihu.com/zvideo/1993097681883637449/
https://www.zhihu.com/zvideo/1993097703345898272
https://www.zhihu.com/zvideo/1993097703345898272/
https://www.zhihu.com/zvideo/1993097692801425645
https://www.zhihu.com/zvideo/1993097692801425645/
https://www.zhihu.com/zvideo/1993097733612008002
https://www.zhihu.com/zvideo/1993097733612008002/
https://www.zhihu.com/zvideo/1993097737290405843
https://www.zhihu.com/zvideo/1993097737290405843/
https://www.zhihu.com/zvideo/1993097744760452563
https://www.zhihu.com/zvideo/1993097744760452563/
https://www.zhihu.com/zvideo/1993097718483142189
https://www.zhihu.com/zvideo/1993097718483142189/
https://www.zhihu.com/zvideo/1993097748447269896
https://www.zhihu.com/zvideo/1993097748447269896/
https://www.zhihu.com/zvideo/1993097741014942106
https://www.zhihu.com/zvideo/1993097741014942106/
https://www.zhihu.com/zvideo/1993097752167601683
https://www.zhihu.com/zvideo/1993097752167601683/
https://www.zhihu.com/zvideo/1993097756940715227
https://www.zhihu.com/zvideo/1993097756940715227/
https://www.zhihu.com/zvideo/1993097790537085629
https://www.zhihu.com/zvideo/1993097790537085629/
https://www.zhihu.com/zvideo/1993097764826009621
https://www.zhihu.com/zvideo/1993097764826009621/
https://www.zhihu.com/zvideo/1993097873986961956
https://www.zhihu.com/zvideo/1993097873986961956/
https://www.zhihu.com/zvideo/1993097774036702583
https://www.zhihu.com/zvideo/1993097774036702583/
https://www.zhihu.com/zvideo/1993097760417789371
https://www.zhihu.com/zvideo/1993097760417789371/
https://www.zhihu.com/zvideo/1993097797625475135
https://www.zhihu.com/zvideo/1993097797625475135/
https://www.zhihu.com/zvideo/1993097786493792544
https://www.zhihu.com/zvideo/1993097786493792544/
https://www.zhihu.com/zvideo/1993097811097563310
https://www.zhihu.com/zvideo/1993097811097563310/
https://www.zhihu.com/zvideo/1993097818521503282
https://www.zhihu.com/zvideo/1993097818521503282/
https://www.zhihu.com/zvideo/1993097806752278390
https://www.zhihu.com/zvideo/1993097806752278390/
https://www.zhihu.com/zvideo/1993097821981794979
https://www.zhihu.com/zvideo/1993097821981794979/
https://www.zhihu.com/zvideo/1993097829154046128
https://www.zhihu.com/zvideo/1993097829154046128/
https://www.zhihu.com/zvideo/1993097801698133563
https://www.zhihu.com/zvideo/1993097801698133563/
https://www.zhihu.com/zvideo/1993097778814011209
https://www.zhihu.com/zvideo/1993097778814011209/
https://www.zhihu.com/zvideo/1993097814562083242
https://www.zhihu.com/zvideo/1993097814562083242/
https://www.zhihu.com/zvideo/1993097794135807916
https://www.zhihu.com/zvideo/1993097794135807916/
https://www.zhihu.com/zvideo/1993097825647600483
https://www.zhihu.com/zvideo/1993097825647600483/
https://www.zhihu.com/zvideo/1993097849911660834
https://www.zhihu.com/zvideo/1993097849911660834/
https://www.zhihu.com/zvideo/1993097768395359808
https://www.zhihu.com/zvideo/1993097768395359808/
https://www.zhihu.com/zvideo/1993097782517601182
https://www.zhihu.com/zvideo/1993097782517601182/
https://www.zhihu.com/zvideo/1993097832853422279
https://www.zhihu.com/zvideo/1993097832853422279/
https://www.zhihu.com/zvideo/1993097855183900703
https://www.zhihu.com/zvideo/1993097855183900703/
https://www.zhihu.com/zvideo/1993097839992120864
https://www.zhihu.com/zvideo/1993097839992120864/
https://www.zhihu.com/zvideo/1993097858560321264
https://www.zhihu.com/zvideo/1993097858560321264/
https://www.zhihu.com/zvideo/1993097870342120280
https://www.zhihu.com/zvideo/1993097870342120280/
https://www.zhihu.com/zvideo/1993097863614443752
https://www.zhihu.com/zvideo/1993097863614443752/
https://www.zhihu.com/zvideo/1993097847214737122
https://www.zhihu.com/zvideo/1993097847214737122/
https://www.zhihu.com/zvideo/1993097852344369803
https://www.zhihu.com/zvideo/1993097852344369803/
https://www.zhihu.com/zvideo/1993097860850419364
https://www.zhihu.com/zvideo/1993097860850419364/
https://www.zhihu.com/zvideo/1993097844089955650
https://www.zhihu.com/zvideo/1993097844089955650/
https://www.zhihu.com/zvideo/1993097887933039472
https://www.zhihu.com/zvideo/1993097887933039472/
https://www.zhihu.com/zvideo/1993097884401439497
https://www.zhihu.com/zvideo/1993097884401439497/
https://www.zhihu.com/zvideo/1993097877413725646
https://www.zhihu.com/zvideo/1993097877413725646/

设计保障:ThreadLocal 本身也做了一些努力,比如在 set()、get()、remove() 的时候,会尝试去清理那些 Key 为 null 的过期 Entry。但这是一种“被动清理”,不能完全依赖。
代码层面:尽量将 ThreadLocal 变量声明为 static final,这样它的生命周期就和类一样长,不会被轻易回收,减少了产生 null Key 的机会。但这并不能替代 remove(),因为线程池复用时,上一个任务的值可能会污染下一个任务。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/1136686.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

RPA赋能人力资源管理:解锁HR高效工作新范式

在企业数字化转型加速的当下&#xff0c;人力资源管理作为企业核心运营环节&#xff0c;正面临着海量重复性工作的效率瓶颈。从招聘期的简历筛选、面试跟进&#xff0c;到入职后的信息录入、考勤统计&#xff0c;再到薪酬核算、离职办理等全流程&#xff0c;传统人工操作不仅耗…

rs232和rs485的区别:抗干扰能力对比说明

工业通信中的“抗干扰王者”之争&#xff1a;RS232为何败给RS485&#xff1f;在自动化车间的某个角落&#xff0c;一台PLC突然停止响应。操作员重启设备、检查线路&#xff0c;却依然无法恢复通信。最终排查发现&#xff0c;问题竟出在那根看似普通的串口线上——它用的是RS232…

东方航空wasm 逆向分析

声明 本文章中所有内容仅供学习交流使用&#xff0c;不用于其他任何目的&#xff0c;抓包内容、敏感网址、数据接口等均已做脱敏处理&#xff0c;严禁用于商业用途和非法用途&#xff0c;否则由此产生的一切后果均与作者无关&#xff01; 部分pyhon代码 data cp.call(req,dat…

Windows下I2C HID驱动加载原理通俗解释

深入理解Windows下的I2C HID驱动加载机制 你有没有遇到过这样的情况&#xff1a;笔记本合盖休眠后&#xff0c;轻点一下触摸板就能唤醒系统&#xff1f;或者在低功耗待机&#xff08;Modern Standby&#xff09;状态下&#xff0c;手指滑动依然灵敏响应&#xff1f;这些看似平…

深度测评2026研究生必用TOP8AI论文网站:开题报告文献综述全攻略

深度测评2026研究生必用TOP8AI论文网站&#xff1a;开题报告文献综述全攻略 2026年研究生必备AI论文工具测评&#xff1a;从开题到终稿的全方位解析 在当前学术研究日益数字化的背景下&#xff0c;AI论文工具已成为研究生群体不可或缺的辅助利器。然而&#xff0c;面对市场上琳…

手把手解析三极管驱动LED时的饱和与截止状态

三极管驱动LED&#xff1a;从“灯亮了”到真正懂电路你有没有过这样的经历&#xff1f;接上电源&#xff0c;LED亮了——心里一喜&#xff1a;“成了&#xff01;”可没过多久&#xff0c;三极管发烫、亮度忽明忽暗&#xff0c;甚至MCU莫名其妙重启……问题出在哪&#xff1f;很…

HDI高密度板线路蚀刻操作指南

HDI高密度板线路蚀刻实战全解&#xff1a;从原理到良率提升的深度剖析你有没有遇到过这样的情况&#xff1f;明明设计时留足了线宽余量&#xff0c;做出来的HDI板却频频出现“短路”报警&#xff1b;或者AOI检测发现边缘模糊、线型收缩&#xff0c;返工一批又一批&#xff0c;良…

鲲鹏DevKit实战经验:从X86到ARM,代码迁移工具(Porting Advisor)的深度解析与实战指南

文章目录前言一、 初识鲲鹏代码迁移工具核心功能概览二、 部署与环境准备三、 实战演练&#xff1a;从源码扫描到代码修改第一步&#xff1a;创建迁移分析任务第二步&#xff1a;解读分析报告第三步&#xff1a;处理C/C源码差异典型场景1&#xff1a;内联汇编&#xff08;Inlin…

SSL是什么?

一句话概括 SSL 是一种用于在互联网上建立加密链接&#xff0c;确保数据在客户端&#xff08;如你的浏览器&#xff09;和服务器&#xff08;如网站&#xff09;之间安全传输 的技术标准。现在它已升级为更安全的 TLS&#xff0c;但人们仍习惯统称为“SSL”。详细解释&#xff…

SSL是什么?

一句话概括 SSL 是一种用于在互联网上建立加密链接&#xff0c;确保数据在客户端&#xff08;如你的浏览器&#xff09;和服务器&#xff08;如网站&#xff09;之间安全传输 的技术标准。现在它已升级为更安全的 TLS&#xff0c;但人们仍习惯统称为“SSL”。详细解释&#xff…

小白指南:RS232接口引脚定义与串口通信基础

从零开始搞懂RS232&#xff1a;不只是引脚定义&#xff0c;更是串口通信的底层逻辑你有没有遇到过这种情况&#xff1f;手头有个温控仪、一台老式PLC&#xff0c;或者工业传感器&#xff0c;说明书上写着“支持串口通信”&#xff0c;接口是个9针的DB9。你拿出USB转TTL模块一接…

隧道洞外亮度检测器 隧道光强检测仪

于长隧道、山区隧道而言&#xff0c;“明暗适应”是影响通行安全的关键痛点——车辆从明亮的洞外快速驶入昏暗的洞内&#xff0c;或从洞内驶出至强光洞外时&#xff0c;强烈的明暗差会导致驾驶员短暂“致盲”&#xff0c;极易引发追尾、碰撞等交通事故。洞外亮度检测器作为隧道…

Packet Tracer新手入门必看:零基础网络模拟学习指南

零基础也能玩转网络&#xff1f;Packet Tracer 实战入门全解析你是不是也曾面对“IP地址”、“子网掩码”、“路由表”这些术语一头雾水&#xff1f;想动手配置路由器&#xff0c;却苦于没有设备、不敢乱试&#xff1f;别急——Cisco Packet Tracer&#xff0c;就是为你量身打造…

图解说明UDS 31服务安全访问时序流程

深入解析UDS 31服务在安全访问中的时序逻辑与实战应用 你有没有遇到过这样的场景&#xff1a;诊断工具连接车辆后&#xff0c;明明发送了正确的“解锁”指令&#xff0c;却始终无法进入写Flash或读取加密数据的权限&#xff1f;反复尝试无果&#xff0c;最后发现是某个隐藏的 …

营养指导实训室:技能实践新空间

一、营养指导实训室的核心功能定位营养指导实训室旨在模拟真实的营养咨询、膳食评估、配餐设计与健康管理场景。其核心功能在于将抽象的营养学知识转化为可操作、可演练的实践技能。在这里&#xff0c;学员能够系统掌握从个体营养状况评估、膳食调查到个性化食谱制定、营养干预…

华为 DevKit 25.2.rc1 源码迁移分析使用教程(openEuler + ARM64)

文章目录一、前言二、准备工作1. 下载所需 RPM 包2. 准备待分析项目三、安装 DevKit1. 卸载旧版本&#xff08;如有&#xff09;2. 按依赖顺序安装 RPM 包四、运行源码迁移分析1. 创建输出目录2. 执行分析命令&#xff08;关键&#xff1a;使用新参数格式&#xff09;3. 等待分…

系统学习MOSFET基本结构与工作逻辑

深入理解MOSFET&#xff1a;从结构到实战的系统性解析你有没有遇到过这样的情况&#xff1f;在设计一个电源电路时&#xff0c;明明选了“大电流”MOSFET&#xff0c;结果一上电就发热严重&#xff1b;或者调试放大器时&#xff0c;增益始终达不到预期——问题可能不在外围电路…

haxm is not installed怎么解决:全面讲解兼容性问题

彻底解决“haxm is not installed”问题&#xff1a;从原理到实战的全链路排查指南 在Android开发中&#xff0c;模拟器是我们日常调试不可或缺的工具。然而&#xff0c;当你满怀期待地点击“Run”按钮时&#xff0c;却弹出一条令人头疼的提示&#xff1a;“ HAXM is not ins…

电网这玩意儿就像走钢丝,随便来个雷击或者设备故障,分分钟给你表演速度和电压的死亡蹦极。但最近咱发现个骚操作——让街边趴着的电动车集体上工当电网保镖

利用插电式电动汽车提高电网暂态稳定性 python联合PSS/E源代码&#xff0c;代码按照高水平文章复现&#xff0c;保证正确 插电式电动汽车(pev)在放电模式下可以作为分布式能源和电力资源&#xff0c;作为车到网(V2G)设备运行;在充电模式下可以作为负载或网到车(G2V)设备运行。 …

通俗解释无源蜂鸣器为何需外部驱动电路

为什么无源蜂鸣器不能直接接单片机&#xff1f;一文讲透驱动原理与电路设计你有没有遇到过这种情况&#xff1a;想用STM32或Arduino控制一个蜂鸣器发出“嘀——”的一声&#xff0c;结果发现有源蜂鸣器能响&#xff0c;换成无源的却一点动静都没有&#xff1f;或者声音微弱、杂…