什么是ThreadLocal

ThreadLocal 是 Java 提供的一个工具类,它为每一个使用该变量的线程都提供了一个独立的变量副本。换句话说:每个线程都有自己的本地变量副本、互不干扰。它不是用来共享数据的,而是用来隔离数据的。

一、为什么需要 ThreadLocal?

考虑一种场景:

  • 你写了一个工具类,这个类在多个线程中并发使用。

  • 你不希望多个线程共享某个变量(比如数据库连接、日期格式化器等),因为那样会造成线程安全问题

这时,就可以使用 ThreadLocal

二、ThreadLocal 的工作原理(简化版)

  • 每个线程对象(Thread)中都有一个 ThreadLocalMap

  • ThreadLocalMap 的 key 是 ThreadLocal 对象本身,value 是对应线程的本地变量副本。

  • 所以,ThreadLocal 实际上是“索引器”,你调用 .set().get(),它会到当前线程的 ThreadLocalMap 里查找对应的值。

三、简单例子

public class ThreadLocalExample {
    // 创建一个 ThreadLocal 变量
    private static ThreadLocal threadLocal = new ThreadLocal<>();

    public static void main(String[] args) {
        Runnable task = () -> {
            // 给当前线程设置值
            threadLocal.set((int) (Math.random() * 100));
            try {
                Thread.sleep(100); // 模拟耗时操作
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            // 获取当前线程的值
            System.out.println(Thread.currentThread().getName() + " 的值:" + threadLocal.get());
        };

        // 启动多个线程
        new Thread(task, "线程A").start();
        new Thread(task, "线程B").start();
    }
}

结果

线程A 的值:42
线程B 的值:87

 

四、常用方法

threadLocal.set(value);   // 设置当前线程的本地值
threadLocal.get();        // 获取当前线程的本地值
threadLocal.remove();     // 删除当前线程的本地值(避免内存泄漏)

五、ThreadLocal 的典型应用场景

  1. 数据库连接管理(如 MyBatis 中的事务控制)

  2. 用户登录信息传递(比如 Spring Security 使用 ThreadLocal 存储当前登录用户)

  3. 日志追踪(Trace ID)

  4. 非线程安全工具的线程隔离(如 SimpleDateFormat

七、注意事项:内存泄漏风险!

在使用线程池时,如果线程复用而你没有调用 ThreadLocal.remove() 清理数据,旧数据可能会一直存在于线程的 ThreadLocalMap 中,从而造成内存泄漏。

解决办法:

  • 用完及时调用 remove()

  • 使用 InheritableThreadLocal 支持线程继承。

  • 在框架中一般封装好,自己写业务逻辑时要留心。

 

你可能感兴趣的:(java,开发语言)