【问题标题】:Java ThreadLocal static?Java ThreadLocal 是静态的吗?
【发布时间】:2013-04-21 09:50:12
【问题描述】:

在线程本地设置一个值:

//Class A holds the static ThreadLocal variable.

    Class A{

    public static ThreadLocal<X> myThreadLocal = new ThreadLocal<X>();             
    ....
    }


//A Class B method sets value in A's static ThreadLocal variable 
    class B{
    {
         public void someBmethod(){
             X x = new X();
             A.myThreadLocal.set(x);
         }
    }


//Class C retrieves the value set in A's Thread Local variable.

    Class C {

    public void someCMethod(){
         X x = A.myThreadLocal.get();
    }
    ...
    }

问题
现在假设这是一个 Web 应用程序,并且线程按顺序执行:B.someBMethod、C.someCMethod。

多个线程执行 B 的 someBMethod,最终会更新 SAME A 的静态 ThreadLocal 变量 myThreadLocal,从而达到 ThreadLocal 变量的目的。 (根据文档建议对 ThreadLocal 使用静态。)

C 的 someCMethod,在从 ThreadLocal 检索值时,可能无法获得“当前”线程设置的值。

我在这里错过了什么?

【问题讨论】:

    标签: java multithreading jakarta-ee thread-local


    【解决方案1】:

    多个线程执行 B 的 someBMethod,最终会更新 SAME A 的静态 ThreadLocal 变量 myThreadLocal

    不,他们不会。每个线程都有自己的 X 类型包含变量的实例。

    从而达到了 ThreadLocal 变量的目的

    没有。

    再看看 Javadoc。

    【讨论】:

    • Java Doc 非常不清楚,因此他问了这个问题,因此我在这里阅读问题和答案:D
    • ThreadLocal 这个名字回答了你的问题,更不用说 Javadoc。仅@NimChimpsky 提供的摘录就足够了。
    【解决方案2】:

    不,他们不会,这就是重点。 Javadoc :

    这些变量与它们的正常对应变量不同之处在于,每个变量 访问一个(通过它的 get 或 set 方法)的线程有它自己的, 独立初始化的变量副本。 ThreadLocal 实例 通常是希望关联的类中的私有静态字段 带有线程的状态(例如,用户 ID 或事务 ID)。

    【讨论】:

      【解决方案3】:

      多个线程执行 B 的 someBMethod,最终会更新 SAME A 的静态 ThreadLocal 变量 myThreadLocal

      是的,它们作用于同一个对象。然而,重要的是要意识到ThreadLocal 的工作方式是每个线程都有自己的独立值。因此,如果您有十个线程写入myThreadLocal,然后从myThreadLocal 读取,每个线程都会看到正确的(即它们自己的)值。

      换句话说,哪个类或对象写入ThreadLocal 的实例并不重要。重要的是在其上下文中执行操作的线程

      【讨论】:

        【解决方案4】:

        根据ThreadLocal类的定义

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

        这意味着说 2 个线程 t1t2 执行 someBMethod() 并且它们最终分别设置 x1x2X 的实例)。现在,当t1 出现并执行someCMethod() 时,它会得到x1(这是自己 之前设置)和t2 得到x2

        换句话说,拥有ThreadLocal 的单个静态实例是安全的,因为当您调用set 时,它在内部会执行类似的操作

        set(currentThread, value) //setting value against that particular thread
        

        当你调用 get 时

        get(currentThread) //getting value for the thread
        

        【讨论】:

        • 在创建线程特定的单例对象时,对此类的需求至关重要......
        【解决方案5】:

        我研究的是java源码

        1. java.lang.Thread Class 包含一个 instance 变量,如下所示。

          ThreadLocal.ThreadLocalMap threadLocals = null;

        因为threadLocals 变量是非静态的,应用程序中的每个线程(即线程类的每个实例)都会有它自己的副本 的 threadLocals 映射。

        1. Key 这个映射是 current ThreadLocal 实例,value 是您作为参数传递的值 到 ThreadLocal.set()。

        2. 当您尝试 fetch 值作为 ThreadLocal.get() 时,在内部,它将从 Current Thread 的 ThreadLocalMap 中获取。

        简单来说,您从当前的线程对象获取和设置值,不是从/到您的 ThreadLocal 对象。

        【讨论】:

          猜你喜欢
          • 2011-02-16
          • 2012-07-20
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-05-04
          • 1970-01-01
          相关资源
          最近更新 更多