新闻中心

j*a threadLocal源码探究

2025-12-07
浏览次数:
返回列表
ThreadLocal 的值存在各线程的 ThreadLocalMap 中,以当前 ThreadLocal 为 key(弱引用)、value 为强引用;需手动 remove() 避免因 key 被 GC 后 value 泄漏。

java threadlocal源码探究

ThreadLocal 的核心不是“全局变量”,而是每个线程独享一份副本,靠的是 Thread 对象内部的 ThreadLocalMap。 它不解决共享数据同步问题,而是规避共享——让每个线程操作自己的变量,天然线程安全。

ThreadLocal 的 set() 是怎么存值的?

调用 threadLocal.set(value) 时,并不会把值存在 ThreadLocal 实例里,而是:

  • 获取当前线程(Thread.currentThread()
  • 从该线程对象中拿到它的 threadLocals 字段(类型是 ThreadLocalMap
  • 以当前 ThreadLocal 实例为 key,传入的 value 为 value,存入这个 map

注意:key 是弱引用(WeakReference<threadlocal></threadlocal>),这是为避免内存泄漏埋下的伏笔。

get() 为什么能拿到“自己”的值?

调用 threadLocal.get() 时流程类似:

  • 拿到当前线程
  • 取出它的 threadLocals(可能为 null,首次调用会触发初始化)
  • 在 map 中以当前 ThreadLocal 实例为 key 查找 entry

由于每个线程都有独立的 ThreadLocalMap,所以自然互不干扰。哪怕多个线程用同一个 ThreadLocal 对象,它们操作的其实是各自 map 中的不同槽位。

ThreadLocalMap 是个什么结构?

它不是 HashMap,而是一个定制的、基于开放寻址法的哈希表:

简小派 简小派

简小派是一款AI原生求职工具,通过简历优化、岗位匹配、项目生成、模拟面试与智能投递,全链路提升求职成功率,帮助普通人更快拿到更好的 offer。

简小派 123 查看详情 简小派
  • 底层是 Entry[] table,Entry 继承自 WeakReference<threadlocal></threadlocal>,value 是强引用
  • 没有链表或红黑树,冲突时线性探测(向后找下一个空位)
  • 每次 get/set 都会顺带做“探测式清理”(expungeStaleEntries):扫描并移除 key 已被 GC 的 stale entry

这个设计兼顾了轻量和性能,但也意味着:如果线程长期运行(如线程池中的线程),又没手动 remove(),就可能因 key 被回收而留下 value 泄漏。

为什么必须手动 remove()?

因为 key 是弱引用,GC 可能随时回收 ThreadLocal 对象,但 value 还牢牢挂在 Entry 里。ThreadLocalMap 的清理是被动且不彻底的(只清理探测路径上的 stale entry)。常见场景如 Web 应用中用 ThreadLocal 存用户上下文,在 Filter 或 Interceptor 结束时务必调用 threadLocal.remove()

不 remove 的后果:线程复用时,旧 value 堆积,引发内存泄漏(尤其 value 是大对象或持有外部引用时)。

基本上就这些。理解 ThreadLocal,关键不在“怎么用”,而在“值到底存在哪”和“谁负责清理”。

以上就是j*a threadLocal源码探究的详细内容,更多请关注其它相关文章!


# 首次  # 北京网站推广亅乐云seo十年  # x济南seo  # 行业信息网站如何推广  # 设计推广营销类方案范文  # seo教程视频王钊  # seo seo顺时学院手把手教  # 网络平台营销推广技巧  # 清远企业网站推广哪家好  # hacci营销推广策略  # 南湖时尚网站建设  # java  # 都有  # 是个  # 这是  # 的是  # 自己的  # 时长  # 转换为  # 全局变量  # 好了  # 为什么 


相关栏目: 【 科技资讯46185 】 【 网络学院92790


相关推荐: 在Qt QML中通过Python字典动态更新TextEdit内容的教程  探索高级语言到C/C++的转译路径:以Go为例及内存管理策略  J*aScript类型检查_j*ascript代码规范  b站如何看历史记录_b站观看历史找回方法  俄罗斯搜索引擎Yandex指南 附2025年免登录官网入口  windows10怎么关闭系统提示音_windows10彻底静音设置方法  windows10怎么查看本机ip_windows10命令提示符ipconfig使用  微信群消息显示延迟如何解决 微信群消息刷新优化方法  Python vgamepad库按键模拟:正确使用XUSB_BUTTON常量  深入理解J*aScript中的B样条曲线与节点向量生成  如何为你的Composer包编写自动化测试_集成PHPUnit到Composer的scripts工作流  创客贴用户入口官网登录 创客贴网页版电脑版系统  痛风发作了怎么办? 快速止痛和后期饮食调理  电脑安装程序提示“错误1722”怎么办_Windows Installer服务问题解决【教程】  高德地图公交到站提醒失败如何解决 高德提醒权限设置  c++如何使用Meson构建系统_c++比CMake更快的构建工具  抖音创作助手登录入口_抖音创作辅助工具官网直达  Win11怎么开启高性能模式_Windows 11电源计划优化设置  PHP中SSG-WSG API的AES加密实践:正确使用初始化向量  谷歌浏览器最新官方入口链接 谷歌浏览器网页版官网导航  UE5.7引擎表现爆炸优化无敌!5090跑4K稳定60FPS  将HTML动态表格多行数据保存到Google Sheet的教程  如何使用CaptainHook和Composer管理Git钩子_在提交前自动运行代码检查的Composer配置  在Typer应用中优雅地处理和重组任意命令行参数  Adobe PDF表单中利用J*aScript解析与格式化日期组件的教程  使用J*aScript检测输入元素是否包含在特定类中  Win10如何清理注册表垃圾 Win10手动清理无效注册表【技巧】  电脑IP地址怎么查 查看本机IP地址的几种方法  黑鲨3Pro怎样在相册开漫画风滤镜_iPhone黑鲨3Pro相册开漫画风滤镜【趣味滤镜】  Golang如何使用new_Go new分配内存机制讲解  文本文档写html代码怎么运行_文本文档html代码运行步骤【教程】  c++如何使用chrono库处理时间_c++标准库时间与日期操作  QQ邮箱网页版邮箱入口 QQ邮箱官方登录平台  React/Next.js中实现列表项的动态选择与移动  Yandex搜索引擎一键访问入口_俄罗斯Yandex官网免登录  XML中包含HTML标签导致解析错误? 正确嵌入非XML数据的两种方法  QQ官网正版登录链接 QQ在线登录入口最新  Python类型检查:优化关联可选属性的Mypy推断策略  Eclipse怎么运行工程_Eclipse工程运行配置说明  python3时间如何用calendar输出?  优化 Jest 模拟:强制未实现函数抛出错误以提升测试效率  夸克浏览器桌面版同步不了书签怎么处理 夸克浏览器跨设备同步异常解决方案  Lar*el如何生成PDF或Excel文件_Lar*el文档导出工具与使用教程  QQ邮箱官方邮箱登录入口 QQ邮箱网页版快速访问  《马克思佩恩3》早期版本曝光 UI设计曾多次调整!  狙击外星人小游戏开始_狙击外星人小游戏立即开始  C++如何实现一个智能指针_手动实现C++ shared_ptr的引用计数功能  豆包手机助手发布技术预览版:直接嵌入手机系统!努比亚样机发售  钉钉视频会议画面卡顿如何解决 钉钉会议画面优化方法  Fabric模组开发:自定义物品与物品组的现代管理方法 

搜索