• ThreadLocal 深度解析

    1. 核心概念

    • 作用:为每个线程提供独立的变量副本,解决多线程并发访问共享变量的冲突问题。
    • 本质:线程级别的全局变量(线程隔离的全局存储)。

    2. 底层原理

    1
    2
    3
    4
    5
    6
    7
    8
    public class ThreadLocal<T> {
    // 关键:每个Thread对象内部维护一个ThreadLocalMap
    public void set(T value) {
    Thread t = Thread.currentThread();
    ThreadLocalMap map = t.threadLocals; // 获取线程专属的Map
    map.set(this, value); // 以ThreadLocal实例为key存储值
    }
    }
    • 存储结构:
      • 每个 Thread 对象内部有一个 ThreadLocalMap(类似HashMap但更简单)。
      • Key:ThreadLocal 实例(弱引用),Value:线程的变量副本。

    3. 使用场景

    场景 说明
    数据库连接管理 每个线程维护独立的Connection(如Spring的TransactionSynchronizationManager
    用户会话信息 在Web应用中存储当前请求的用户信息(如Spring Security的SecurityContextHolder
    日期格式化工具 避免SimpleDateFormat线程不安全问题

    4. 使用示例

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    // 1. 定义ThreadLocal变量
    private static final ThreadLocal<User> currentUser = ThreadLocal.withInitial(() -> null);

    // 2. 设置当前线程的值
    currentUser.set(user);

    // 3. 获取当前线程的值
    User user = currentUser.get();

    // 4. 使用后必须清理!防止内存泄漏
    currentUser.remove();

    5. 内存泄漏问题

    • 原因:

      • ThreadLocalMap 的 Key 是弱引用,但 Value 是强引用。
      • 线程池中线程长期存活时,Value 可能无法被回收。
    • 解决方案:

      • 每次使用后调用 remove() 清理。

      • 使用

        1
        try-finally

        确保清理:

        1
        2
        3
        4
        5
        6
        try {
        currentUser.set(user);
        // 业务逻辑...
        } finally {
        currentUser.remove();
        }

    6. 与synchronized对比

    特性 ThreadLocal synchronized
    作用范围 线程隔离 线程互斥
    性能开销 无锁,更快 有锁竞争,可能阻塞
    适用场景 线程间数据隔离 线程间同步控制

    7.相关问题

    • Q1:ThreadLocal如何实现线程隔离?
      A:每个Thread内部维护独立的ThreadLocalMap,以ThreadLocal实例为Key存储值。
    • Q2:为什么Key用弱引用?
      A:防止ThreadLocal对象无法被回收(但仍需手动remove()避免Value泄漏)。
    • Q3:Spring如何用ThreadLocal管理事务?
      A:TransactionSynchronizationManager 用ThreadLocal保存当前线程的数据库连接。