当前位置: 首页 > news >正文

【Java后端基础 005】ThreadLocal-线程数据共享和安全

608564A16E7D652E882914E830EE4050(1)


📚博客主页:代码探秘者

✨专栏:文章正在持续更新ing…

✅C语言/C++:C++(详细版) 数据结构) 十大排序算法

✅Java基础:JavaSE基础 面向对象大合集 JavaSE进阶 Java版数据结构JDK新特性

✅前端基础: 前端三剑客 必学前端技术栈

✅后端经典框架: 后端基础 SpringBoot Tlias项目(含SSM)

✅数据库:Mysql

✅常用中间件:redis入门+实战 Elasticsearch RabbitMQ

✅Linux: 部署篇

✅微服务:微服务

❤️感谢大家点赞👍🏻收藏⭐评论✍🏻,您的三连就是我持续更新的动力❤️

🙏作者水平有限,欢迎各位大佬指点,相互学习进步!


img

文章目录

  • 线程数据共享和安全 -ThreadLocal
    • 🧠1. 什么是 ThreadLocal?
      • 🔧 ThreadLocal 常用方法
      • 🎯 典型用途场景(保存用户登录信息(如当前用户 ID))
    • 2.解析
      • 🎯 1. 作用:线程内共享变量,解决线程安全问题
      • 🧷 2. 存值方法:`set()` 给当前线程绑定数据
      • 🔍 3. 获取方法:`get()` 相当于线程私有 Map 的 `get(key)`
      • 🧩 4. 一个 ThreadLocal 对象 = 一个数据槽位
      • 🧱 5. 建议使用 `static` 修饰 ThreadLocal 实例
      • 🧹 6. 自动释放内存(前提:线程终结)
    • 其他常见注意
    • 📦 延伸阅读

线程数据共享和安全 -ThreadLocal


🧠1. 什么是 ThreadLocal?

ThreadLocal 是 Java 提供的线程本地变量工具类,它为每个线程提供了一个独立的变量副本。

  • 本质:为每个线程分配独立副本,不共享数据
  • 用途:解决多线程中共享变量引起的数据混乱

1.ThreadLocal 的作用,可以实现在同一个线程数据共享, 从而解决多线程数据安全问题.

2.ThreadLocal 可以给当前线程关联一个数据(普通变量、对象、数组)set 方法 [源码!]

3.ThreadLocal 可以像 Map 一样存取数据,key 为当前线程, get 方法

4.每一个 ThreadLocal 对象, 只能为当前线程关联一个数据,如果要为当前线程关联多个数 据,就需要使用多个 ThreadLocal 对象实例

5.每个 ThreadLocal 对象实例定义的时候,一般为 static 类型

6.ThreadLocal 中保存数据,在线程销毁后,会自动释放(建议手动释放) 。


🔧 ThreadLocal 常用方法

方法说明
set(T value)设置当前线程的变量值
get()获取当前线程的变量值
remove()移除当前线程的变量值,避免内存泄漏(重要

🎯 典型用途场景(保存用户登录信息(如当前用户 ID))

public class UserContext {private static final ThreadLocal<Long> userIdHolder = new ThreadLocal<>();public static void setUserId(Long id) {userIdHolder.set(id);}public static Long getUserId() {return userIdHolder.get();}public static void clear() {userIdHolder.remove();}
}

📍通常配合拦截器、过滤器、JWT 使用:登录验证完后存入 ThreadLocal,业务代码就能直接获取当前用户 ID,无需每层传参。

当然也可以保存用户的一些信息

private static final ThreadLocal<UserDTO> tl = new ThreadLocal<>();

2.解析


🎯 1. 作用:线程内共享变量,解决线程安全问题

ThreadLocal 可实现线程内的数据共享,从而避免多线程访问共享数据造成冲突。


🧷 2. 存值方法:set() 给当前线程绑定数据

🧪 可绑定 基本类型 / 对象 / 数组 / Map 等 任意数据

threadLocal.set("userId-123");

🔍 3. 获取方法:get() 相当于线程私有 Map 的 get(key)

🗂️ 每个线程维护一份 ThreadLocalMap,key 是线程,value 是你 set 的值

String value = threadLocal.get();

🧩 4. 一个 ThreadLocal 对象 = 一个数据槽位

📦 想为同一线程绑定多个值?你就要 new 多个 ThreadLocal 实例,例如:

public static ThreadLocal<String> userName = new ThreadLocal<>();
public static ThreadLocal<Long> userId = new ThreadLocal<>();

🧱 5. 建议使用 static 修饰 ThreadLocal 实例

🧷 常作为工具类全局使用,方便访问、只初始化一次

public static final ThreadLocal<String> threadLocal = new ThreadLocal<>();

🧹 6. 自动释放内存(前提:线程终结)

🛡️ 线程销毁后,ThreadLocal 中数据会被自动 GC 清理
❗ 但如果线程池中复用线程,必须手动调用 remove() 防止内存泄漏

threadLocal.remove();  // 非常重要

其他常见注意


✅ 数据库多数据源切换

用 ThreadLocal 存放当前线程使用的数据源标识,在 AOP 或拦截器中切换。


✅ 日志 traceId 链路追踪(如打印统一 traceId)


🧱 ThreadLocal 与并发安全

情况是否线程安全
普通变量❌ 多线程共享,容易数据混乱
ThreadLocal✅ 每个线程独立副本,互不影响

⚠️ 注意事项(新手必须知道)

🔺 一定要手动 remove()!

  • 原因:ThreadLocal 引用的是线程私有变量,线程池复用线程时可能出现 内存泄漏
  • 解决:
    • 处理完必须调用 ThreadLocal.remove()
    • 或使用 try-finally 包裹清除逻辑
try {ThreadLocalHolder.set(value);// 业务处理
} finally {ThreadLocalHolder.remove();
}

📦 延伸阅读

内容推荐方向
ThreadLocalMap底层实现结构(Map)
InheritableThreadLocal子线程继承父线程变量
Spring 中的使用RequestContextHolderSecurityContextHolder
与线程池结合使用后强制清理,尤其注意 @AsyncCompletableFuture

相关文章:

  • vue3子组件获取并修改父组件的值
  • 企业私有化部署的平价革命:五步实现“低成本高可控”AI落地——破除百万投入迷思,中小企业也能玩转私有化大模型
  • 李沐《动手学深度学习》d2l安装教程
  • 在 Windows 系统上运行 Docker 容器中的 Ubuntu 镜像并显示 GUI
  • window查看SVN账号密码
  • 第四十六天打卡
  • 华为 “一底双长焦” 专利公布,引领移动影像新变革
  • vue中加载Cesium地图(天地图、高德地图)
  • 解决基于LangGraph框架的DeerFlow使用Qwen3不能正常被解析的问题
  • SOC-ESP32S3部分:31-ESP-LCD控制器库
  • TeamCity Agent 配置完整教程(配合 Docker Compose 快速部署)
  • Vite 双引擎架构 —— Esbuild 概念篇
  • Self Attention自注意力机制
  • 使用 Docker Compose 从零部署 TeamCity + PostgreSQL(详细新手教程)
  • Ubuntu 系统通过防火墙管控 Docker 容器
  • 【PyQt5】用于设置控件位置的参数
  • 【Kotlin】注解反射扩展
  • [大A量化专栏] 夏普比率
  • Linux 下的COW机制(copy-on-write)
  • android app 一个 crash的解决过程!
  • javaweb一个旅游网站怎么做/软文范例大全500
  • 有什么正网站做兼职的/windows优化大师要会员
  • 重庆做网站建设公司排名/深圳刚刚突然宣布
  • wordpress限制单独站点大小/宁波网络优化seo
  • 安徽华夏网站建设/seo
  • 淘宝 客要推广网站怎么做/比较正规的代运营