news 2026/4/23 11:14:30

每个线程有自己的 ThreadLocalMap 副本哈希表结构:使用开放地址法解决哈希

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
每个线程有自己的 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/1993465785503467014
https://www.zhihu.com/zvideo/1993465785503467014/
https://www.zhihu.com/zvideo/1993465790100431843
https://www.zhihu.com/zvideo/1993465790100431843/
https://www.zhihu.com/zvideo/1993465793992732744
https://www.zhihu.com/zvideo/1993465793992732744/
https://www.zhihu.com/zvideo/1993465798249947734
https://www.zhihu.com/zvideo/1993465798249947734/
https://www.zhihu.com/zvideo/1993465802368784134
https://www.zhihu.com/zvideo/1993465802368784134/
https://www.zhihu.com/zvideo/1993465806336590643
https://www.zhihu.com/zvideo/1993465806336590643/
https://www.zhihu.com/zvideo/1993465810887393796
https://www.zhihu.com/zvideo/1993465810887393796/
https://www.zhihu.com/zvideo/1993465815337559641
https://www.zhihu.com/zvideo/1993465815337559641/
https://www.zhihu.com/zvideo/1993465819397632308
https://www.zhihu.com/zvideo/1993465819397632308/
https://www.zhihu.com/zvideo/1993465823612920622
https://www.zhihu.com/zvideo/1993465823612920622/
https://www.zhihu.com/zvideo/1993465828096623223
https://www.zhihu.com/zvideo/1993465828096623223/
https://www.zhihu.com/zvideo/1993465832236392834
https://www.zhihu.com/zvideo/1993465832236392834/
https://www.zhihu.com/zvideo/1993465836275533258
https://www.zhihu.com/zvideo/1993465836275533258/
https://www.zhihu.com/zvideo/1993465848602591398
https://www.zhihu.com/zvideo/1993465848602591398/
https://www.zhihu.com/zvideo/1993465861495873997
https://www.zhihu.com/zvideo/1993465861495873997/
https://www.zhihu.com/zvideo/1993465840495002880
https://www.zhihu.com/zvideo/1993465840495002880/
https://www.zhihu.com/zvideo/1993465844534112334
https://www.zhihu.com/zvideo/1993465844534112334/
https://www.zhihu.com/zvideo/1993465853178581027
https://www.zhihu.com/zvideo/1993465853178581027/
https://www.zhihu.com/zvideo/1993465863895024969
https://www.zhihu.com/zvideo/1993465863895024969/
https://www.zhihu.com/zvideo/1993465857314150034
https://www.zhihu.com/zvideo/1993465857314150034/
https://www.zhihu.com/zvideo/1993465868827527163
https://www.zhihu.com/zvideo/1993465868827527163/
https://www.zhihu.com/zvideo/1993465866310930755
https://www.zhihu.com/zvideo/1993465866310930755/
https://www.zhihu.com/zvideo/1993465871264409112
https://www.zhihu.com/zvideo/1993465871264409112/
https://www.zhihu.com/zvideo/1993465891174782190
https://www.zhihu.com/zvideo/1993465891174782190/
https://www.zhihu.com/zvideo/1993465873848082935
https://www.zhihu.com/zvideo/1993465873848082935/
https://www.zhihu.com/zvideo/1993465878814147173
https://www.zhihu.com/zvideo/1993465878814147173/
https://www.zhihu.com/zvideo/1993465885973836813
https://www.zhihu.com/zvideo/1993465885973836813/
https://www.zhihu.com/zvideo/1993465883633415530
https://www.zhihu.com/zvideo/1993465883633415530/
https://www.zhihu.com/zvideo/1993465881162973378
https://www.zhihu.com/zvideo/1993465881162973378/
https://www.zhihu.com/zvideo/1993465896258257293
https://www.zhihu.com/zvideo/1993465896258257293/
https://www.zhihu.com/zvideo/1993465876171744919
https://www.zhihu.com/zvideo/1993465876171744919/
https://www.zhihu.com/zvideo/1993465893792014578
https://www.zhihu.com/zvideo/1993465893792014578/
https://www.zhihu.com/zvideo/1993465888800805055
https://www.zhihu.com/zvideo/1993465888800805055/
https://www.zhihu.com/zvideo/1993465898791625363
https://www.zhihu.com/zvideo/1993465898791625363/
https://www.zhihu.com/zvideo/1993465901551477067
https://www.zhihu.com/zvideo/1993465901551477067/
https://www.zhihu.com/zvideo/1993465906278451160
https://www.zhihu.com/zvideo/1993465906278451160/
https://www.zhihu.com/zvideo/1993465908799247887
https://www.zhihu.com/zvideo/1993465908799247887/
https://www.zhihu.com/zvideo/1993465911114499506
https://www.zhihu.com/zvideo/1993465911114499506/
https://www.zhihu.com/zvideo/1993465916227342874
https://www.zhihu.com/zvideo/1993465916227342874/
https://www.zhihu.com/zvideo/1993465913840791958
https://www.zhihu.com/zvideo/1993465913840791958/
https://www.zhihu.com/zvideo/1993465921147249180
https://www.zhihu.com/zvideo/1993465921147249180/
https://www.zhihu.com/zvideo/1993465918844584033
https://www.zhihu.com/zvideo/1993465918844584033/
https://www.zhihu.com/zvideo/1993465928252408369
https://www.zhihu.com/zvideo/1993465928252408369/
https://www.zhihu.com/zvideo/1993465926000072480
https://www.zhihu.com/zvideo/1993465926000072480/
https://www.zhihu.com/zvideo/1993465933323333916
https://www.zhihu.com/zvideo/1993465933323333916/
https://www.zhihu.com/zvideo/1993465931083572446
https://www.zhihu.com/zvideo/1993465931083572446/
https://www.zhihu.com/zvideo/1993465923533807829
https://www.zhihu.com/zvideo/1993465923533807829/
https://www.zhihu.com/zvideo/1993465935701491882
https://www.zhihu.com/zvideo/1993465935701491882/
https://www.zhihu.com/zvideo/1993465948636738959
https://www.zhihu.com/zvideo/1993465948636738959/
https://www.zhihu.com/zvideo/1993465938058688265
https://www.zhihu.com/zvideo/1993465938058688265/
https://www.zhihu.com/zvideo/1993465958195549595
https://www.zhihu.com/zvideo/1993465958195549595/
https://www.zhihu.com/zvideo/1993465943658088066
https://www.zhihu.com/zvideo/1993465943658088066/
https://www.zhihu.com/zvideo/1993465953908970084
https://www.zhihu.com/zvideo/1993465953908970084/
https://www.zhihu.com/zvideo/1993465962335319042
https://www.zhihu.com/zvideo/1993465962335319042/
https://www.zhihu.com/zvideo/1993465970803630168
https://www.zhihu.com/zvideo/1993465970803630168/
https://www.zhihu.com/zvideo/1993465966479298912
https://www.zhihu.com/zvideo/1993465966479298912/
https://www.zhihu.com/zvideo/1993465974909838619
https://www.zhihu.com/zvideo/1993465974909838619/
https://www.zhihu.com/zvideo/1993465978923798743
https://www.zhihu.com/zvideo/1993465978923798743/
https://www.zhihu.com/zvideo/1993465987304030625
https://www.zhihu.com/zvideo/1993465987304030625/
https://www.zhihu.com/zvideo/1993465983181013059
https://www.zhihu.com/zvideo/1993465983181013059/
https://www.zhihu.com/zvideo/1993465991708030248
https://www.zhihu.com/zvideo/1993465991708030248/
https://www.zhihu.com/zvideo/1993465996057543700
https://www.zhihu.com/zvideo/1993465996057543700/
https://www.zhihu.com/zvideo/1993466003951199315
https://www.zhihu.com/zvideo/1993466003951199315/
https://www.zhihu.com/zvideo/1993466045076354213
https://www.zhihu.com/zvideo/1993466045076354213/
https://www.zhihu.com/zvideo/1993466000058905087
https://www.zhihu.com/zvideo/1993466000058905087/
https://www.zhihu.com/zvideo/1993466008078410997
https://www.zhihu.com/zvideo/1993466008078410997/
https://www.zhihu.com/zvideo/1993466016244725086
https://www.zhihu.com/zvideo/1993466016244725086/
https://www.zhihu.com/zvideo/1993466034951320544
https://www.zhihu.com/zvideo/1993466034951320544/
https://www.zhihu.com/zvideo/1993466037157524521
https://www.zhihu.com/zvideo/1993466037157524521/
https://www.zhihu.com/zvideo/1993466054563881774
https://www.zhihu.com/zvideo/1993466054563881774/
https://www.zhihu.com/zvideo/1993466028152338292
https://www.zhihu.com/zvideo/1993466028152338292/
https://www.zhihu.com/zvideo/1993466023433754190
https://www.zhihu.com/zvideo/1993466023433754190/
https://www.zhihu.com/zvideo/1993466012155285726
https://www.zhihu.com/zvideo/1993466012155285726/
https://www.zhihu.com/zvideo/1993466032535410197
https://www.zhihu.com/zvideo/1993466032535410197/
https://www.zhihu.com/zvideo/1993466049841108361
https://www.zhihu.com/zvideo/1993466049841108361/
https://www.zhihu.com/zvideo/1993466084238566486
https://www.zhihu.com/zvideo/1993466084238566486/
https://www.zhihu.com/zvideo/1993466021118506101
https://www.zhihu.com/zvideo/1993466021118506101/
https://www.zhihu.com/zvideo/1993466030316594079
https://www.zhihu.com/zvideo/1993466030316594079/
https://www.zhihu.com/zvideo/1993466047567787948
https://www.zhihu.com/zvideo/1993466047567787948/
https://www.zhihu.com/zvideo/1993466041779651863
https://www.zhihu.com/zvideo/1993466041779651863/
https://www.zhihu.com/zvideo/1993466062033929766
https://www.zhihu.com/zvideo/1993466062033929766/
https://www.zhihu.com/zvideo/1993466069390734751
https://www.zhihu.com/zvideo/1993466069390734751/
https://www.zhihu.com/zvideo/1993466052248621501
https://www.zhihu.com/zvideo/1993466052248621501/
https://www.zhihu.com/zvideo/1993466018778083891
https://www.zhihu.com/zvideo/1993466018778083891/
https://www.zhihu.com/zvideo/1993466064353375347
https://www.zhihu.com/zvideo/1993466064353375347/
https://www.zhihu.com/zvideo/1993466076764329477
https://www.zhihu.com/zvideo/1993466076764329477/
https://www.zhihu.com/zvideo/1993466059563479235
https://www.zhihu.com/zvideo/1993466059563479235/
https://www.zhihu.com/zvideo/1993466071735366298
https://www.zhihu.com/zvideo/1993466071735366298/
https://www.zhihu.com/zvideo/1993466057017553844
https://www.zhihu.com/zvideo/1993466057017553844/
https://www.zhihu.com/zvideo/1993466074344223759
https://www.zhihu.com/zvideo/1993466074344223759/
https://www.zhihu.com/zvideo/1993466079629026046
https://www.zhihu.com/zvideo/1993466079629026046/
https://www.zhihu.com/zvideo/1993466081810072188
https://www.zhihu.com/zvideo/1993466081810072188/
https://www.zhihu.com/zvideo/1993466067150976711
https://www.zhihu.com/zvideo/1993466067150976711/
https://www.zhihu.com/zvideo/1993466088986517911
https://www.zhihu.com/zvideo/1993466088986517911/
https://www.zhihu.com/zvideo/1993466086608359562
https://www.zhihu.com/zvideo/1993466086608359562/
https://www.zhihu.com/zvideo/1993466093776422574
https://www.zhihu.com/zvideo/1993466093776422574/
https://www.zhihu.com/zvideo/1993466091415048376
https://www.zhihu.com/zvideo/1993466091415048376/

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

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

基于Python+Django的车辆检测服务中心管理系统设计与实现

前言 &#x1f31e;博主介绍&#xff1a;✌CSDN特邀作者、全栈领域优质创作者、10年IT从业经验、码云/掘金/知乎/B站/华为云/阿里云等平台优质作者、专注于Java、小程序/APP、python、大数据等技术领域和毕业项目实战&#xff0c;以及程序定制化开发、文档编写、答疑辅导等。✌…

作者头像 李华
网站建设 2026/4/22 14:40:34

新手入门必看:Vector工具链基础操作与AUTOSAR关联

从零开始理解 Vector 工具链与 AUTOSAR 的工程实践你是不是刚接触汽车电子开发&#xff0c;面对 DaVinci、RTE、ARXML 这些术语一头雾水&#xff1f;或者已经看过不少资料&#xff0c;但始终搞不清&#xff1a;AUTOSAR 到底是怎么通过一堆工具变成实际运行的代码的&#xff1f;…

作者头像 李华
网站建设 2026/4/21 17:43:54

ST7735电源管理模块详解超详细版

ST7735电源管理深度实战&#xff1a;如何让TFT屏功耗从30mA降到2μA&#xff1f;你有没有遇到过这样的情况&#xff1f;项目快收尾了&#xff0c;测试电池续航时却发现——明明MCU已经进入Deep Sleep&#xff0c;电流也压到了几微安&#xff0c;可整机待机电流还是下不去。一查…

作者头像 李华
网站建设 2026/4/17 8:27:04

从STM32视角看CANFD和CAN的区别:通俗解释带宽差异

从STM32视角看CAN FD与经典CAN的差异&#xff1a;一场关于带宽、效率和未来的对话 你有没有遇到过这样的场景&#xff1f; 在调试一个基于STM32的电池管理系统时&#xff0c;主控MCU需要从多个从节点读取电压、温度和SOC数据。每帧只有8字节的经典CAN协议&#xff0c;逼得你不…

作者头像 李华
网站建设 2026/4/19 15:24:26

[特殊字符]_可扩展性架构设计:从单体到微服务的性能演进[20260110164857]

作为一名经历过多次系统架构演进的老兵&#xff0c;我深知可扩展性对Web应用的重要性。从单体架构到微服务&#xff0c;我见证了无数系统在扩展性上的成败。今天我要分享的是基于真实项目经验的Web框架可扩展性设计实战。 &#x1f4a1; 可扩展性的核心挑战 在系统架构演进过…

作者头像 李华
网站建设 2026/4/17 18:47:19

C++ 变量作用域

局部变量局部变量在函数或代码块内部声明&#xff0c;仅在该函数或代码块内有效。生命周期从声明开始到代码块结束。例如&#xff1a;void func() {int x 10; // 局部变量cout << x; // 有效 } // cout << x; // 错误&#xff1a;x在此处不可见全局变量全局变量…

作者头像 李华