news 2026/6/10 21:21:06

我从原理、场景和内存泄漏三个方面

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
我从原理、场景和内存泄漏三个方面

一、核心原理
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/1993466431875086211
https://www.zhihu.com/zvideo/1993466431875086211/
https://www.zhihu.com/zvideo/1993466505136971920
https://www.zhihu.com/zvideo/1993466505136971920/
https://www.zhihu.com/zvideo/1993466419388647022
https://www.zhihu.com/zvideo/1993466419388647022/
https://www.zhihu.com/zvideo/1993466423884932078
https://www.zhihu.com/zvideo/1993466423884932078/
https://www.zhihu.com/zvideo/1993466427814981788
https://www.zhihu.com/zvideo/1993466427814981788/
https://www.zhihu.com/zvideo/1993466436719502700
https://www.zhihu.com/zvideo/1993466436719502700/
https://www.zhihu.com/zvideo/1993466512753844410
https://www.zhihu.com/zvideo/1993466512753844410/
https://www.zhihu.com/zvideo/1993466441421329605
https://www.zhihu.com/zvideo/1993466441421329605/
https://www.zhihu.com/zvideo/1993466445443646627
https://www.zhihu.com/zvideo/1993466445443646627/
https://www.zhihu.com/zvideo/1993466450258712234
https://www.zhihu.com/zvideo/1993466450258712234/
https://www.zhihu.com/zvideo/1993466454859858034
https://www.zhihu.com/zvideo/1993466454859858034/
https://www.zhihu.com/zvideo/1993466482009580516
https://www.zhihu.com/zvideo/1993466482009580516/
https://www.zhihu.com/zvideo/1993466473444827371
https://www.zhihu.com/zvideo/1993466473444827371/
https://www.zhihu.com/zvideo/1993466459465216987
https://www.zhihu.com/zvideo/1993466459465216987/
https://www.zhihu.com/zvideo/1993466464863291270
https://www.zhihu.com/zvideo/1993466464863291270/
https://www.zhihu.com/zvideo/1993466468889796976
https://www.zhihu.com/zvideo/1993466468889796976/
https://www.zhihu.com/zvideo/1993466478155027846
https://www.zhihu.com/zvideo/1993466478155027846/
https://www.zhihu.com/zvideo/1993466489991344675
https://www.zhihu.com/zvideo/1993466489991344675/
https://www.zhihu.com/zvideo/1993466485893525706
https://www.zhihu.com/zvideo/1993466485893525706/
https://www.zhihu.com/zvideo/1993466498325435945
https://www.zhihu.com/zvideo/1993466498325435945/
https://www.zhihu.com/zvideo/1993466493900443661
https://www.zhihu.com/zvideo/1993466493900443661/
https://www.zhihu.com/zvideo/1993466502729450072
https://www.zhihu.com/zvideo/1993466502729450072/
https://www.zhihu.com/zvideo/1993466510262412456
https://www.zhihu.com/zvideo/1993466510262412456/
https://www.zhihu.com/zvideo/1993466515480129929
https://www.zhihu.com/zvideo/1993466515480129929/
https://www.zhihu.com/zvideo/1993466507712291030
https://www.zhihu.com/zvideo/1993466507712291030/
https://www.zhihu.com/zvideo/1993466517975740592
https://www.zhihu.com/zvideo/1993466517975740592/
https://www.zhihu.com/zvideo/1993466520265839104
https://www.zhihu.com/zvideo/1993466520265839104/
https://www.zhihu.com/zvideo/1993466546350220799
https://www.zhihu.com/zvideo/1993466546350220799/
https://www.zhihu.com/zvideo/1993466558459170972
https://www.zhihu.com/zvideo/1993466558459170972/
https://www.zhihu.com/zvideo/1993466541862323192
https://www.zhihu.com/zvideo/1993466541862323192/
https://www.zhihu.com/zvideo/1993466529388438265
https://www.zhihu.com/zvideo/1993466529388438265/
https://www.zhihu.com/zvideo/1993466536380355210
https://www.zhihu.com/zvideo/1993466536380355210/
https://www.zhihu.com/zvideo/1993466531821150814
https://www.zhihu.com/zvideo/1993466531821150814/
https://www.zhihu.com/zvideo/1993466526976730627
https://www.zhihu.com/zvideo/1993466526976730627/
https://www.zhihu.com/zvideo/1993466522908263024
https://www.zhihu.com/zvideo/1993466522908263024/
https://www.zhihu.com/zvideo/1993466538892739471
https://www.zhihu.com/zvideo/1993466538892739471/
https://www.zhihu.com/zvideo/1993466634795521027
https://www.zhihu.com/zvideo/1993466634795521027/
https://www.zhihu.com/zvideo/1993466548812276709
https://www.zhihu.com/zvideo/1993466548812276709/
https://www.zhihu.com/zvideo/1993466544118851394
https://www.zhihu.com/zvideo/1993466544118851394/
https://www.zhihu.com/zvideo/1993466561093185831
https://www.zhihu.com/zvideo/1993466561093185831/
https://www.zhihu.com/zvideo/1993466556097771285
https://www.zhihu.com/zvideo/1993466556097771285/
https://www.zhihu.com/zvideo/1993466553568605015
https://www.zhihu.com/zvideo/1993466553568605015/
https://www.zhihu.com/zvideo/1993466566398980351
https://www.zhihu.com/zvideo/1993466566398980351/
https://www.zhihu.com/zvideo/1993466551278524225
https://www.zhihu.com/zvideo/1993466551278524225/
https://www.zhihu.com/zvideo/1993466563605583054
https://www.zhihu.com/zvideo/1993466563605583054/
https://www.zhihu.com/zvideo/1993466568781341118
https://www.zhihu.com/zvideo/1993466568781341118/
https://www.zhihu.com/zvideo/1993466573780971872
https://www.zhihu.com/zvideo/1993466573780971872/
https://www.zhihu.com/zvideo/1993466576402417503
https://www.zhihu.com/zvideo/1993466576402417503/
https://www.zhihu.com/zvideo/1993466571369251821
https://www.zhihu.com/zvideo/1993466571369251821/
https://www.zhihu.com/zvideo/1993466588029019208
https://www.zhihu.com/zvideo/1993466588029019208/
https://www.zhihu.com/zvideo/1993466578973528332
https://www.zhihu.com/zvideo/1993466578973528332/
https://www.zhihu.com/zvideo/1993466592076529822
https://www.zhihu.com/zvideo/1993466592076529822/
https://www.zhihu.com/zvideo/1993466583943758749
https://www.zhihu.com/zvideo/1993466583943758749/
https://www.zhihu.com/zvideo/1993466600997791248
https://www.zhihu.com/zvideo/1993466600997791248/
https://www.zhihu.com/zvideo/1993466727166678938
https://www.zhihu.com/zvideo/1993466727166678938/
https://www.zhihu.com/zvideo/1993466613924655779
https://www.zhihu.com/zvideo/1993466613924655779/
https://www.zhihu.com/zvideo/1993466605234037135
https://www.zhihu.com/zvideo/1993466605234037135/
https://www.zhihu.com/zvideo/1993466626469807712
https://www.zhihu.com/zvideo/1993466626469807712/
https://www.zhihu.com/zvideo/1993466622002882395
https://www.zhihu.com/zvideo/1993466622002882395/
https://www.zhihu.com/zvideo/1993466618043467605
https://www.zhihu.com/zvideo/1993466618043467605/
https://www.zhihu.com/zvideo/1993466596497314054
https://www.zhihu.com/zvideo/1993466596497314054/
https://www.zhihu.com/zvideo/1993466630441829209
https://www.zhihu.com/zvideo/1993466630441829209/
https://www.zhihu.com/zvideo/1993466724704609992
https://www.zhihu.com/zvideo/1993466724704609992/
https://www.zhihu.com/zvideo/1993466639509918019
https://www.zhihu.com/zvideo/1993466639509918019/
https://www.zhihu.com/zvideo/1993466673764787626
https://www.zhihu.com/zvideo/1993466673764787626/
https://www.zhihu.com/zvideo/1993466647609111922
https://www.zhihu.com/zvideo/1993466647609111922/
https://www.zhihu.com/zvideo/1993466660758254354
https://www.zhihu.com/zvideo/1993466660758254354/
https://www.zhihu.com/zvideo/1993466686230251177
https://www.zhihu.com/zvideo/1993466686230251177/
https://www.zhihu.com/zvideo/1993466668203123768
https://www.zhihu.com/zvideo/1993466668203123768/
https://www.zhihu.com/zvideo/1993466658308767853
https://www.zhihu.com/zvideo/1993466658308767853/
https://www.zhihu.com/zvideo/1993466688667157219
https://www.zhihu.com/zvideo/1993466688667157219/
https://www.zhihu.com/zvideo/1993466698670547261
https://www.zhihu.com/zvideo/1993466698670547261/
https://www.zhihu.com/zvideo/1993466691238240702
https://www.zhihu.com/zvideo/1993466691238240702/
https://www.zhihu.com/zvideo/1993466683709477406
https://www.zhihu.com/zvideo/1993466683709477406/
https://www.zhihu.com/zvideo/1993466675975169131
https://www.zhihu.com/zvideo/1993466675975169131/
https://www.zhihu.com/zvideo/1993466663572640005
https://www.zhihu.com/zvideo/1993466663572640005/
https://www.zhihu.com/zvideo/1993466651706930835
https://www.zhihu.com/zvideo/1993466651706930835/
https://www.zhihu.com/zvideo/1993466678995085242
https://www.zhihu.com/zvideo/1993466678995085242/
https://www.zhihu.com/zvideo/1993466708984370820
https://www.zhihu.com/zvideo/1993466708984370820/
https://www.zhihu.com/zvideo/1993466696309168032
https://www.zhihu.com/zvideo/1993466696309168032/
https://www.zhihu.com/zvideo/1993466643452557037
https://www.zhihu.com/zvideo/1993466643452557037/
https://www.zhihu.com/zvideo/1993466681385842604
https://www.zhihu.com/zvideo/1993466681385842604/
https://www.zhihu.com/zvideo/1993466732480852302
https://www.zhihu.com/zvideo/1993466732480852302/
https://www.zhihu.com/zvideo/1993466730035581523
https://www.zhihu.com/zvideo/1993466730035581523/
https://www.zhihu.com/zvideo/1993466717511366414
https://www.zhihu.com/zvideo/1993466717511366414/
https://www.zhihu.com/zvideo/1993466711157011544
https://www.zhihu.com/zvideo/1993466711157011544/
https://www.zhihu.com/zvideo/1993466705670845526
https://www.zhihu.com/zvideo/1993466705670845526/
https://www.zhihu.com/zvideo/1993466665975976049
https://www.zhihu.com/zvideo/1993466665975976049/
https://www.zhihu.com/zvideo/1993466655951561631
https://www.zhihu.com/zvideo/1993466655951561631/
https://www.zhihu.com/zvideo/1993466735077134559
https://www.zhihu.com/zvideo/1993466735077134559/
https://www.zhihu.com/zvideo/1993466670459667762
https://www.zhihu.com/zvideo/1993466670459667762/
https://www.zhihu.com/zvideo/1993466703431103668
https://www.zhihu.com/zvideo/1993466703431103668/
https://www.zhihu.com/zvideo/1993466693872263506
https://www.zhihu.com/zvideo/1993466693872263506/
https://www.zhihu.com/zvideo/1993466722150291252
https://www.zhihu.com/zvideo/1993466722150291252/
https://www.zhihu.com/zvideo/1993466701174547157
https://www.zhihu.com/zvideo/1993466701174547157/
https://www.zhihu.com/zvideo/1993466737769849166
https://www.zhihu.com/zvideo/1993466737769849166/
https://www.zhihu.com/zvideo/1993466713728104244
https://www.zhihu.com/zvideo/1993466713728104244/

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

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/10 19:26:15

STM32CubeMX下载后的第一个LED闪烁项目从零实现

从零开始点亮第一盏LED&#xff1a;STM32CubeMX实战入门全记录 你有没有过这样的经历&#xff1f;下载完STM32CubeMX&#xff0c;打开软件却不知道下一步该点哪里&#xff1b;好不容易生成了代码&#xff0c;编译烧录后LED却不亮……别担心&#xff0c;这几乎是每个嵌入式新手…

作者头像 李华
网站建设 2026/6/10 12:48:52

AD导出Gerber文件时层设置的系统学习

Altium Designer导出Gerber文件&#xff1a;从层设置到生产交付的实战指南在电子硬件开发中&#xff0c;完成PCB布局布线只是走完了“万里长征第一步”。真正决定产品能否顺利投产的关键一步——把设计准确无误地交给工厂制造&#xff0c;往往被许多工程师轻视甚至忽视。而这个…

作者头像 李华
网站建设 2026/5/30 18:19:34

基于STM32的工业控制ISR配置手把手教程

手把手教你打造工业级实时响应系统&#xff1a;STM32中断配置实战全解析在工厂的自动化产线上&#xff0c;一个电机突然过流&#xff0c;控制系统必须在几毫秒内切断电源&#xff1b;一台机器人手臂接近障碍物&#xff0c;安全光栅信号必须被立即捕获并处理&#xff1b;PLC需要…

作者头像 李华
网站建设 2026/6/10 9:17:53

STM32开发入门:Keil5安装与配置手把手教程

从零开始搭建STM32开发环境&#xff1a;Keil5安装与配置实战指南 你是不是也曾在准备动手写第一行代码时&#xff0c;被一堆工具链、驱动和配置项搞得晕头转向&#xff1f;明明只是想点亮一个LED&#xff0c;却卡在“无法连接目标”或者“找不到芯片”这种问题上。别急——这几…

作者头像 李华
网站建设 2026/6/10 14:32:18

Multisim汉化实战:软件层修改完整指南

Multisim汉化实战&#xff1a;从资源修改到自动化部署的完整技术路径你有没有遇到过这样的场景&#xff1f;打开Multisim准备做电路仿真&#xff0c;刚点开“Place”菜单就卡住了——Ground是接地还是电源&#xff1f;Probe到底该译成“探针”还是“探测器”&#xff1f;对于初…

作者头像 李华
网站建设 2026/6/10 20:01:23

工业网关开发中的CubeMX安装避坑指南

工业网关开发实战&#xff1a;STM32CubeMX安装避坑全记录 在我们最近的一个工业边缘计算项目中&#xff0c;团队刚拿到新设计的STM32H743核心板&#xff0c;准备着手开发支持Modbus、CAN和以太网协议转换的智能网关。一切就绪&#xff0c;却卡在了最基础的一环—— STM32Cube…

作者头像 李华