何时ThreadLocal优先于局部变量?

时间:2016-07-19 01:39:02

标签: java multithreading stack thread-local

Java中的

ThreadLocal表示:

  

Java中的ThreadLocal类使您可以创建只能由同一线程读取和写入的变量。因此,即使两个线程正在执行相同的代码,并且代码具有对ThreadLocal变量的引用,那么这两个线程也看不到彼此的ThreadLocal变量。

我的问题是:当我们需要获取一个特定于线程的变量时,我们不能只将该变量声明为方法中的局部变量吗?因为每个线程都有自己的堆栈,因此它获得了自己的变量副本。我在这里错过了什么吗?

3 个答案:

答案 0 :(得分:2)

ThreadLocal不是是本地变量的替代品。您将ThreadLocal用于必须为static的数据,但不得在线程之间共享。

static final ThreadLocal<MyFoo> myFoo =
    ThreadLocal.withInitial(() -> new MyFoo());

如果您的ThreadLocal变量不是static,那么您要么做一些过于复杂的事情,或者您正在做一些事情,那就是&#39 ;这是完全错误的。

另一方面,如果您有static的任何变量(无论是ThreadLocal还是(option_id => Option_value,option_id => Option_value) ),那么您应该知道这是一个限制您的设计选择能够测试和发展该计划。

答案 1 :(得分:0)

  

当状态需要时,ThreadLocal可能是最佳选择   与线程相关的例如全局变量(如果语义允许)   因为ThreadLocal将变量值保留在线程中;所以   当一个线程T运行时,线程T得到设置的值   本身不是任何其他线程。

来自this文章。

当变量位于线程的类本身内部并且范围是每个线程的本地变量时,可以使用局部变量。与此相反,当变量在局部范围之外并作为共享代码的一部分存在并且语义允许每个线程保留此变量的副本而不是所有线程的单个副本时,则使用ThreadLocal。

答案 2 :(得分:0)

根据oracle文档,

ThreadLocal用于不同目的。

看看这堂课的意图:

  

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

下面的代码块生成每个线程本地的唯一标识符。线程的id在第一次调用ThreadId.get()时被分配,并在后续调用中保持不变。

 import java.util.concurrent.atomic.AtomicInteger;

 public class ThreadId {
     // Atomic integer containing the next thread ID to be assigned
     private static final AtomicInteger nextId = new AtomicInteger(0);

     // Thread local variable containing each thread's ID
     private static final ThreadLocal<Integer> threadId =
         new ThreadLocal<Integer>() {
             @Override protected Integer initialValue() {
                 return nextId.getAndIncrement();
         }
     };

     // Returns the current thread's unique ID, assigning it if necessary
     public static int get() {
         return threadId.get();
     }
 }

回到您的查询:

  

当我们需要获取一个特定于线程的变量时,我们不能只将该变量声明为方法中的局部变量吗?因为每个线程都有自己的堆栈,因此它获得了自己的变量副本。我在这里错过了什么吗?

是。你在这里遗漏了一些东西。

在方法内声明的变量范围以方法生命周期结束。

对于ThreadLocal变量,只要线程处于活动状态且ThreadLocal实例可访问,每个线程都会保存对其线程局部变量副本的隐式引用。您可以在其生命周期中多次重新输入该线程,但仍然可以保留该变量。