【问题标题】:How ThreadLocal variable passes copy of its object to different Threads in java?ThreadLocal 变量如何将其对象的副本传递给 java 中的不同线程?
【发布时间】:2026-02-18 17:15:01
【问题描述】:

下面是创建线程局部变量的例子

private static final ThreadLocal<SimpleDateFormat> formatter = new ThreadLocal<SimpleDateFormat>(){
    @Override
    protected SimpleDateFormat initialValue()
    {
        return new SimpleDateFormat("yyyyMMdd HHmm");
    }
};

还有第二种使用线程本地的方法

public class MyThreadLocal {

    public static final ThreadLocal userThreadLocal = new ThreadLocal();

    public static void set(Context user) {
        userThreadLocal.set(user);
    }

    public static void unset() {
        userThreadLocal.remove();
    }

    public static Context get() {
        return userThreadLocal.get();
    }
}

现在,下面一行创建了一个线程局部变量,它是静态的。

public static final ThreadLocal userThreadLocal = new ThreadLocal();

每当在 JVM 中加载类时,都会初始化静态变量。这意味着在加载类时会创建一个对象。

**问题: *当不同的 Thread 调用 ThreadLocal 变量的 Set 或 get 时,threadlocal 对象的副本是如何传递给线程的?*每个 Thread 是如何获取自己的对象的? 如果在加载类时创建了一个对象,那么这是怎么回事?**

【问题讨论】:

  • 你看过源代码吗?
  • @DuncanJones 没有邓肯

标签: java thread-local


【解决方案1】:

这其实是线程实现的一部分。

原则上,您可以认为每个 Thread 实例都有一个 Map,其中 ThreadLocal 对象实例(只有一个)是 key,与之关联的 value 是 value。

ThreadLocal 的静态实例根本不保存值,它只是一个标记,供 Thread 再次查找(Thread 存储值)。

所以

userThreadLocal.get();

有点像

currentThread.privateMapOfThreadLocalValues.get(userThreadLocal);      

【讨论】:

  • 对,你说的对,我忘了是通过map实现的。
【解决方案2】:

我认为ThreadLocal的文档中已经清楚地描述了答案

总结一下我引用

这个类提供线程局部变量。这些变量不同 与它们的正常对应物不同,每个线程访问一个 (通过它的 get 或 set 方法)有自己的、独立初始化的 变量的副本。 ThreadLocal 实例通常是私有的 希望将状态与线程相关联的类中的静态字段 (例如,用户 ID 或交易 ID)。

每个线程都包含对其本地线程副本的隐式引用 只要线程处于活动状态并且 ThreadLocal 实例就可以变量 可访问;在一个线程消失后,它的所有副本 线程本地实例受到垃圾收集(除非其他 存在对这些副本的引用)。

希望这可以澄清。

【讨论】: