Wrayの知识库 Wrayの知识库
首页
  • Java 基础
  • Java 集合
  • Java 并发
  • Java IO
  • JVM
  • Spring Framework
  • Spring Boot
  • Spring Cloud
  • Spring Security
  • MySQL
  • Redis
  • 计算机基础
  • 操作系统原理
  • Linux
  • MacOS
  • Windows
  • 系统工程与研究专题
  • AI 基础
  • 大模型基础
  • Prompt 工程
  • RAG 检索增强生成
  • Agent 智能体
  • AI 应用开发
  • AI 工程化
  • AI 安全与治理
  • AI 面试与设计题
  • 纸质书
  • 电子书
  • 学习课程
疑难杂症
GitHub (opens new window)
首页
  • Java 基础
  • Java 集合
  • Java 并发
  • Java IO
  • JVM
  • Spring Framework
  • Spring Boot
  • Spring Cloud
  • Spring Security
  • MySQL
  • Redis
  • 计算机基础
  • 操作系统原理
  • Linux
  • MacOS
  • Windows
  • 系统工程与研究专题
  • AI 基础
  • 大模型基础
  • Prompt 工程
  • RAG 检索增强生成
  • Agent 智能体
  • AI 应用开发
  • AI 工程化
  • AI 安全与治理
  • AI 面试与设计题
  • 纸质书
  • 电子书
  • 学习课程
疑难杂症
GitHub (opens new window)
  • Java章节编写规范
  • Java基础

  • Java集合

  • Java并发

    • Java并发概述
    • 线程与进程
    • Thread类与线程生命周期
    • 线程创建与任务模型
    • 线程安全
    • synchronized关键字
    • volatile关键字
    • Java内存模型(JMM)
    • 线程间通信
    • 线程池
    • 并发工具类
    • 原子操作类Atomic
    • 并发锁
    • 并发容器
    • ConcurrentHashMap
    • BlockingQueue
    • CopyOnWriteArrayList
    • ThreadLocal
      • 1. 基本用法
      • 2. 底层模型
      • 3. 常见场景
      • 4. 内存泄漏风险
      • 5. 弱引用 key
      • 6. 线程池与上下文传递
      • 7. InheritableThreadLocal
      • 8. 使用原则
      • 专家实践与边界
      • Tips 快问快答
    • Fork/Join框架
    • ScheduledThreadPoolExecutor
    • CompletableFuture
    • 虚拟线程
    • 死锁活锁与线程问题排查
    • 并发编程最佳实践
  • Java IO

  • JVM

  • Java
  • Java并发
Wray
2026-06-24
目录

ThreadLocal

ThreadLocal 为每个线程保存一份独立变量副本,常用于线程上下文传递和线程内状态隔离。

它不是解决共享变量竞争的锁,而是让变量不共享。

# 1. 基本用法

private static final ThreadLocal<String> USER_ID = new ThreadLocal<>();

public void handle(String userId) {
    try {
        USER_ID.set(userId);
        doWork();
    } finally {
        USER_ID.remove();
    }
}

读取:

String userId = USER_ID.get();

# 2. 底层模型

每个线程内部有自己的 ThreadLocalMap。

Thread A
└─ ThreadLocalMap
   └─ USER_ID -> "1001"

Thread B
└─ ThreadLocalMap
   └─ USER_ID -> "2002"

同一个 ThreadLocal 对象,在不同线程中对应不同值。

# 3. 常见场景

  • 当前用户 ID。
  • TraceId / 请求链路 ID。
  • 租户 ID。
  • 数据源上下文。
  • 事务上下文。
  • 日期格式化器旧方案。

例如日志链路:

请求进入 -> set traceId
业务调用 -> 日志自动读取 traceId
请求结束 -> remove traceId

# 4. 内存泄漏风险

线程池中线程会复用,如果不 remove,旧请求数据可能留在线程里。

请求 A 在线程 T 设置 userId=A
请求 A 结束但未 remove
线程 T 被复用处理请求 B
请求 B 可能读到 A 的 userId

必须:

try {
    threadLocal.set(value);
    doWork();
} finally {
    threadLocal.remove();
}

# 5. 弱引用 key

ThreadLocalMap 的 key 是弱引用,但 value 是强引用。

Entry
├─ key: WeakReference&lt;ThreadLocal>
└─ value: Object 强引用

如果 ThreadLocal 对象被回收,但线程长期存活,value 仍可能滞留。因此即使 key 是弱引用,也必须主动 remove。

# 6. 线程池与上下文传递

ThreadLocal 不会自动跨线程传递。

USER_ID.set("1001");
executor.submit(() -> {
    USER_ID.get(); // 通常取不到
});

解决思路:

  • 显式把上下文作为参数传入。
  • 提交任务时包装 Runnable/Callable。
  • 使用框架提供的上下文传递能力。
  • 谨慎使用 InheritableThreadLocal,线程池下容易不符合预期。

# 7. InheritableThreadLocal

它可以让子线程创建时继承父线程值。

InheritableThreadLocal<String> local = new InheritableThreadLocal<>();

但线程池中的线程通常早已创建,后续任务不是新建子线程,因此继承行为经常不符合预期。

# 8. 使用原则

  • 用于线程内上下文,不要当全局变量。
  • set 后必须在 finally 中 remove。
  • 值对象不要过大。
  • 在线程池异步任务中不要假设上下文自动传播。
  • 能用方法参数显式传递时,优先显式传递。

# 专家实践与边界

ThreadLocal 解决的是线程内上下文隔离,不是线程间共享。它常用于 traceId、登录用户、租户、事务上下文等“同一线程调用链都要访问”的信息。

Thread
  └─ ThreadLocalMap
       ├─ ThreadLocal A -> valueA
       └─ ThreadLocal B -> valueB
场景 是否适合 注意点
请求 traceId 适合 请求结束必须清理
用户上下文 适合 线程池复用会串数据
大对象缓存 不适合 容易内存泄漏
跨线程传递 默认不适合 需要显式包装
异步任务上下文 谨慎 CompletableFuture 不自动传播

在线程池环境中,线程会被复用。如果请求结束不 remove,下一个请求可能读到上一个请求的上下文,这类 bug 隐蔽且危险。

# Tips 快问快答

Q:ThreadLocal 解决线程安全吗? A:它通过线程隔离避免共享,不是锁。

Q:ThreadLocal 的值存在哪里? A:存在线程自己的 ThreadLocalMap 中。

Q:为什么一定要 remove? A:线程池线程会复用,不 remove 可能造成数据污染和内存泄漏。

Q:ThreadLocal 会自动传给线程池任务吗? A:不会。

Q:InheritableThreadLocal 在线程池里可靠吗? A:通常不可靠,因为线程池线程不是每次任务新建。

Q:ThreadLocalMap key 是弱引用就不会泄漏吗? A:不是,value 仍可能被长期持有。

Q:TraceId 可以用 ThreadLocal 吗? A:可以,但异步任务要处理上下文传递和清理。

Q:能用参数传递还要用 ThreadLocal 吗? A:优先显式参数,ThreadLocal 适合横切上下文。

上次更新: 2026/06/25, 14:19:18
CopyOnWriteArrayList
Fork/Join框架

← CopyOnWriteArrayList Fork/Join框架→

Copyright © 2023-2026 Wray | 鄂ICP备2024050235号-1
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式