Java高级主题:深入解析ThreadLocal的数据结构设计原理及其源代码实现
ThreadLocal可以实现完全基于无锁且也不是基于CAS的线程隔离需求,让每个线程可以有自己的本地实例,但如果对ThreadLocal底层设计不了解,那么对甚至无法正确ThreadLocal及其可能出现的内存泄露问题。可以说ThreadLocal的源代码设计也一种非常优秀的可支持“高并发”的实现。1、基本用法:1.1 demo1publicclassThreadLocalDemo{staticclassProducerAextendsThread{@Overridepublicvoidrun(){ThreadLocalStringvar1=newThreadLocal();ThreadLocalStringvar2=newThreadLocal();// 普通用法var1.set("foo A");var2.set("bar A");System.out.println(var1.get());// 输出foo ASystem.out.println(var2.get());// 输出bar A}}staticclassProducerBextendsThread{@Overridepublicvoidrun(){ThreadLocalStringvar1=newThreadLocal();ThreadLocalStringvar2=newThreadLocal();// 普通用法var1.set("foo B");var2.set("bar B");System.out.println(var1.get());// 输出foo BSystem.out.println(var2.get());// 输出bar B}}publicstaticvoidmain(String[]args){newProducerA().start();newProducerB().start();}}这里创建了两个线程,每个线程内部有自己的ThreadLocal变量,线程之间ThreadLocal变量内部的set和get互相独立,互不影响,无需使用锁即可实现了线程安全操作。线程内部的变量使用set方法给定初始值、get方法取值,可以猜测其内部有类似HashMap这样的设计,但是否照搬HashMap数据结构设计呢? 其实不然,在这里,ProducerA内部创建了一个ThreadLocalMap,ProducerB内部也创建了一个ThreadLocalMap,也即每个线程绑定一个自己内部ThreadLocalMap,这里提到的ThreadLocalMap就是提供了set、get方法的底层Map数据结构,所谓的ThreadLocal数据结构分析其实就是特指其内部的ThreadLocalMap的数据结构分析。1.2 demo2publicclassThreadLocalDemo{staticclassHoldCount{intcount;finallongtid=0;}publicstaticvoidmain(String[]args){ThreadLocalHoldCountrh=ThreadLocal.withInitial(HoldCount::new);// 设定rh这个ThreadLocal变量的初始值rh.set(newHoldCount());// 将计数器放在rh中缓存HoldCounth=rh.get();System.out.println(h.count);// 这里输出的rh初始值,也即HoldCount的count属性初始值:0。for(inti=0;i10;i++){h.count++;}System.out.println(h.count);HoldCountnewh=rh.get();// 更新缓存计数器后,再从ThreadLocal重新读取System.out.println(newh.count);// 可以读取新的计数值// 在rh这个ThreadLocal里面的Map结构中移除HoldCount实例对象rh.remove();System.out.println(rh.get());// 此时rh里面Map已经不存在HoldCount对象,因此这里返回NUll}}在demo2中,给出了使用ThreadLocal后需要及时删除其实例对象的情况,这部分原因将在文章后面给出深入分析。2、ThreadLocal内部数据结构简析可以看到set方法是由内部ThreadLocalMap实现的set方法,既然是个“Map”,那么当然可以猜测是否跟HashMap的数据结构:数据+链表+红黑树类似呢?publicvoidset(Tvalue){Threadt=Thread.currentThread();ThreadLocalMapmap=getMap(t);if(map!=null)map.set(this,value);elsecreateMap(t,value);}其实ThreadLocalMap的数据结构没有HashMap数据结构复杂,ThreadLocalMap底层仅有一个table数组,这里,也许你会好奇:HashMap为了解决hash冲突,在数组的桶位上加入一条单向链表,冲突的entry自然会放入到此链表中(或者红黑树),那么问题来了,ThreadLocalMap底层仅有一个table数组,它是如何解决hash冲突?以下正式其设计原理之一,这里的数组给出最简单的情况,不包括“stale entry(无效entry)”的情况,以便让读者快速理解ThreadLocalMap设计原理:可以看到图中所说的“解决冲突的方式:从i=3开始向后遍历出首个空slot,也即i=5,将keyC放入此空slot即可”的逻辑被称为“线性探测法”,所谓的“线性”就是o(n)复杂度的遍历操作,所谓的“探测”就是不断向后“探测、寻找”,直到找到首个空slot位置。以上内容为ThreadLocalMap的放入new Entry的简单情况,如果有理解HashMap源代码设计的读者应该可以猜到其他重要设计:例如,当数组容量不够时,如何扩容,也即rehash(注意ThreadLocalMap里面的resize和rehash不是同一个逻辑),再例如ThreadLocalMap里面已经存在的entry,如果它的key已经变成无效(stale),那么如何该清理,或者说在set和get的线性探测过程中遇到有stale entry时,该如何清理?这些问题将在后面逐个深入探讨。3、ThreadLocalMap基本成员变量的说明staticclassThreadLocalMap{/** * The entries in this hash map extend WeakReference, using * its main ref field as the key (which is always a * ThreadLocal object). Note that null keys (i.e. entry.get() * == null) mean that the key is no longer referenced, so the * entry can be expunged from table. Such entries are referred to * as "stale entries" in the code that follows. */// ThreadLocalMap底层数组存放的WeakReference类型的entry,使用弱引用类型是为了能够高效GC,避免内存泄露,文章后面给出此设计的讨论staticclassEntryextendsWeakReferenceThreadLocal?{/** The value associated with this ThreadLocal. */Objectvalue;/* entry的key就是ThreadLocal对象,例如一个线程内部有10个ThreadLocal变量,那么此线程内部的ThreadLocalMap将存放这10个entry,这里的value就是ThreadLocal变量的“值”。 例如demo1中: ThreadLocalString var1=new ThreadLocal(); var1.set("foo A") 那么entry的key就是这个名称为var1的ThreadLocal对象,value就是字符串“foo A” */Entry(ThreadLocal?k,Objectv){super(k);value=v;}}/** * The initial capacity -- MUST be a power of two. */// 数组的初始容量16privatestaticfinalintINITIAL_CAPACITY=16;/** * The table, resized as necessary. * table.length MUST always be a power of two. *///ThreadLocalMap的底层数组,这里也采用2的次方,原因在HashMap的源代码讨论已经给出深入的解析,这里不再累赘。privateEntry[]table;/** * The number of entries in the table. */// 数据含有entry的个数,注意即使entry的key处于stale状态,它也算一个entryprivateintsize=0;/** * The next size value at which to resize. */privateintthreshold;// Default to 0/** * Set the resize thr

相关新闻

瑞德克斯平台:投教内容的要点盘点

瑞德克斯平台:投教内容的要点盘点

外汇市场信息更新频繁,平台口碑的形成更依赖长期一致性:入口是否好找、说明是否前后一致、提示是否稳定出现。围绕瑞德克斯平台,下面从稳定体验与信息呈现等角度做一次正面观察。外汇相关平台的价值,体现在长期一致性与信息呈现的…

2026/7/28 21:41:00阅读更多 →
LangChain实战:大模型RAG与Agent智能体的长期会话记忆实现

LangChain实战:大模型RAG与Agent智能体的长期会话记忆实现

1. 项目概述:大模型RAG与Agent智能体实战中的长期会话记忆在构建基于大模型的智能对话系统时,长期会话记忆是实现自然交互的核心能力。想象一下,当你与人类客服交流时,对方能记住你之前提过的需求和个人信息,这种连续性…

2026/7/28 21:41:00阅读更多 →
hot100 最长公共子序列(1143)

hot100 最长公共子序列(1143)

本题采用二维动态规划 (2D Dynamic Programming) 算法解决双字符串最长公共子序列 (LCS, Longest Common Subsequence) 的求解问题。其核心本质是将两个序列的全局拓扑匹配问题,拆解为二维状态空间阵列中的自底向上一维步进收敛模型。通过构建大小为 (m 1) * (n 1…

2026/7/28 21:41:00阅读更多 →
能源路由器厂商全景解析:技术路线、核心产品与选型参考

能源路由器厂商全景解析:技术路线、核心产品与选型参考

随着AI数据中心单机柜功耗从8kW向120kW甚至更高水平跃升,传统AC 10kV/380V工频变压器加UPS的供电模式正面临越来越大的压力。低压大电流带来的线损、散热和布线难题,驱动行业加速探索从"多级变换"向"一级直供"的架构演进。在这一背景…

2026/7/28 22:41:20阅读更多 →
Poppins字体完整指南:如何免费获取这款现代几何无衬线字体

Poppins字体完整指南:如何免费获取这款现代几何无衬线字体

Poppins字体完整指南:如何免费获取这款现代几何无衬线字体 【免费下载链接】Poppins Poppins, a Devanagari Latin family for Google Fonts. 项目地址: https://gitcode.com/gh_mirrors/po/Poppins Poppins是一款结合了天城文和拉丁文的现代几何无衬线字体…

2026/7/28 22:41:20阅读更多 →
提供一些高密度UPS的具体型号:智算时代兆瓦级供电方案选型深度解析

提供一些高密度UPS的具体型号:智算时代兆瓦级供电方案选型深度解析

数据中心正在经历一场以功率密度为核心的系统级重构。单机柜功耗从过去的5至8kW跃升至40至120kW甚至更高,一个万卡GPU集群的供电需求轻松突破数兆瓦。在这种趋势下,高密度UPS已经从可选项变为智算中心配电架构中的核心决策项。了解当前市场上主流高密度U…

2026/7/28 22:41:20阅读更多 →
企业办公AI系统定制服务商本地部署与文档智能开发方案推荐

企业办公AI系统定制服务商本地部署与文档智能开发方案推荐

要说我们公司最头疼的事儿,文档处理绝对排前三。销售合同、采购合同、技术文档、客户资料、内部制度……每年光是处理这些文档的人力成本就大几十万。而且最要命的是,很多文档还涉及商业机密,绝对不能外传。所以当我开始找企业办公AI系统定制…

2026/7/28 22:41:20阅读更多 →
免费终极指南:如何快速部署本地化Meta-Llama-3.1-8B-Instruct-GGUF大语言模型

免费终极指南:如何快速部署本地化Meta-Llama-3.1-8B-Instruct-GGUF大语言模型

免费终极指南:如何快速部署本地化Meta-Llama-3.1-8B-Instruct-GGUF大语言模型 【免费下载链接】Meta-Llama-3.1-8B-Instruct-GGUF 项目地址: https://ai.gitcode.com/hf_mirrors/bartowski/Meta-Llama-3.1-8B-Instruct-GGUF 你是否厌倦了依赖云端AI服务的高…

2026/7/28 22:41:20阅读更多 →
M9A自动化引擎架构解析:如何构建基于图像识别的游戏智能代理系统

M9A自动化引擎架构解析:如何构建基于图像识别的游戏智能代理系统

M9A自动化引擎架构解析:如何构建基于图像识别的游戏智能代理系统 【免费下载链接】M9A 重返未来:1999 小助手 | Assistant For Reverse: 1999 项目地址: https://gitcode.com/gh_mirrors/m9/M9A M9A是基于MaaFramework图像识别框架构建的《重返未…

2026/7/28 22:39:20阅读更多 →
覆盖国产 + 海外 + 开源模型,OpenClaw 2.7.9 Windows/Mac 双端部署详解

覆盖国产 + 海外 + 开源模型,OpenClaw 2.7.9 Windows/Mac 双端部署详解

🔹 工具基础介绍 OpenClaw 是开源生态中一款实用性较强的本地智能工具,凭借本地离线运行、可视化图形操作和任务自动化三大核心特性,赢得了众多用户的青睐。与普通在线对话AI工具不同,它属于能够直接操控本机软硬件的智能数字员工…

2026/7/28 4:06:39阅读更多 →
伺服阀焊完微漏毁整机?精密激光焊接三关锁住高压

伺服阀焊完微漏毁整机?精密激光焊接三关锁住高压

所谓液压伺服阀体的精密激光焊接,是用激光束对阀座壳体(通常为不锈钢或铝合金)进行密封焊接,使阀体在21-35MPa的高压液压油或压缩气体中长期运行而不发生介质泄漏。液压伺服阀是高端液压系统的"大脑"。从航空航天飞行控…

2026/7/28 2:08:06阅读更多 →
D2DX:三步实现《暗黑破坏神2》高清宽屏体验的终极指南

D2DX:三步实现《暗黑破坏神2》高清宽屏体验的终极指南

D2DX:三步实现《暗黑破坏神2》高清宽屏体验的终极指南 【免费下载链接】d2dx D2DX is a complete solution to make Diablo II run well on modern PCs, with high fps and better resolutions. 项目地址: https://gitcode.com/gh_mirrors/d2/d2dx 你是否还在…

2026/7/28 1:38:28阅读更多 →
告别臃肿!3步让你的暗影精灵笔记本重获新生

告别臃肿!3步让你的暗影精灵笔记本重获新生

告别臃肿!3步让你的暗影精灵笔记本重获新生 【免费下载链接】OmenSuperHub Control Omen laptop performance, fan speeds, and keyboard lighting, and unlock power limits. 项目地址: https://gitcode.com/gh_mirrors/om/OmenSuperHub 你是否也曾为官方Om…

2026/7/28 0:00:29阅读更多 →
RAG必踩坑!财报法规检索不准?这款开源工具让答案浮出水面,准确率飙升98.7%!

RAG必踩坑!财报法规检索不准?这款开源工具让答案浮出水面,准确率飙升98.7%!

做 RAG 的人应该都踩过这个致命的坑:把几百页的财报、法规、技术手册扔给向量库,问一个具体问题,搜出来的全是沾边但没用的内容 —— 关键信息要么被硬切块拆碎了,要么藏在几十条结果的最下面。语义相似≠真正相关,这个…

2026/7/28 0:00:29阅读更多 →
抖音视频文案提取工具全指南:免费2026版、手机App、在线工具一网打尽

抖音视频文案提取工具全指南:免费2026版、手机App、在线工具一网打尽

2026年做短视频运营,从抖音上扒文案早就不是偷偷抄笔记的事了。我刚开始做内容的时候,每天刷半小时抖音,手动把爆款视频的口播敲进备忘录,一条2分钟的视频得花十来分钟,碰到语速快的还要反复回听。后来试了一圈工具&am…

2026/7/28 0:00:29阅读更多 →
YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

如果你在部署 YOLOv8 时,发现推理速度只有可怜的 1-2 FPS,而别人的演示视频却能跑到 30 FPS 以上,那么问题很可能不在模型本身,而在于你的整个处理链路。很多开发者拿到一个训练好的 YOLOv8 模型后,会直接使用官方示例…

2026/7/28 20:22:24阅读更多 →
Coze与Dify对比指南:低代码AI应用开发从入门到实战

Coze与Dify对比指南:低代码AI应用开发从入门到实战

1. 从零到一:为什么你需要了解 Coze 和 Dify?如果你对 AI 应用开发感兴趣,但一看到“大模型”、“智能体”、“工作流”这些词就头疼,觉得门槛太高,那这篇文章就是为你准备的。很多开发者,包括我自己&#…

2026/7/28 3:17:03阅读更多 →
AI生图工具怎么选?2026年6月版实测对比

AI生图工具怎么选?2026年6月版实测对比

做自媒体的朋友应该都有体会:配图一直是个让人头疼的问题。2026年,AI生图工具已经非常成熟了,但工具太多反而不知道怎么选。以下是截至2026年6月我对主流AI生图工具的实测对比。Midjourney V8.1:速度之王2026年6月11日&#xff0c…

2026/7/28 2:35:58阅读更多 →