Java ThreadLocal静态?

Jas*_*per 17 java multithreading thread-local java-ee

在线程本地中设置值:

//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();
    }
    ...
    }
Run Code Online (Sandbox Code Playgroud)

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

执行B的someBMethod的多个线程将最终更新SAME A的静态ThreadLocal变量myThreadLocal,从而击败了ThreadLocal变量的目的.(对于ThreadLocal使用静态是根据文档推荐的.)

C的someCMethod,虽然从ThreadLocal中检索值可能无法获得"当前"线程设置的值.

我在这里失踪了什么?

san*_*hat 52

根据ThreadLocal类的定义

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

这意味着说2个线程t1t2执行someBMethod(),它们最终分别设置x1&x2(Instances of X).现在什么时候t1来执行someCMethod()它得到x1(由它自己设置)并得到.t2x2

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

set(currentThread, value) //setting value against that particular thread
Run Code Online (Sandbox Code Playgroud)

当你调用get

get(currentThread) //getting value for the thread
Run Code Online (Sandbox Code Playgroud)


NPE*_*NPE 5

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

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

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


Sun*_*amy 5

我研究了Java 源代码

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

    ThreadLocal.ThreadLocalMap threadLocals = null;

因为threadLocals变量是非静态的,所以应用程序中的每个线程(即Thread Class的每个实例)将拥有它自己的threadLocals映射副本

  1. 该映射的当前 ThreadLocal实例,而value是您作为参数传递给ThreadLocal.set()的值。

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

简而言之,您是从当前线程对象获取&设置值,而不是ThreadLocal对象获取&设置值。