ThreadLocal变量

时间:2017-12-15 04:19:58

标签: java

ThreadLocal变量如何降低创建昂贵对象的成本?

例如:

private ThreadLocal<String> myThreadLocal = new ThreadLocal<String>();

在上面的一行中,我们创建了一个ThreadLocal对象,它将为thread创建一个对象。但是我无法理解如何降低创建实例的成本。

4 个答案:

答案 0 :(得分:3)

昂贵通常意味着需要一段时间,但这也意味着它会占用很多其他资源。

就像实例变量是每个实例一样,ThreadLocal变量是每个线程。它是一种为昂贵的创建对象实现线程安全的方法。

对于前。 SimpleDateFormat,通过使它成为ThreadLocal,你可以使它成为线程安全的。由于该类很昂贵,因此在本地范围内使用它并不好,这需要在每次调用时使用单独的实例。

通过为每个线程提供自己的副本:

1)通过重复使用固定数量的实例来减少昂贵对象的实例数量。

2)实现线程安全,无需同步或不变性。

答案 1 :(得分:1)

  

ThreadLocal变量如何降低创建昂贵对象的成本?

它不会降低创建对象的成本,ThreadLocal的单个实例可以独立地为每个线程存储不同的值。

TheadLocal构造允许我们存储只能由特定线程访问的数据。

假设我们想要一个与特定线程捆绑在一起的Integer值:

ThreadLocal<Integer> threadLocalValue = new ThreadLocal<>();

接下来,当我们想要从线程中使用这个值时,我们只需要调用get()或set()方法。简单地说,我们可以认为ThreadLocal将数据存储在地图中 - 以线程作为关键。

由于这个事实,当我们在threadLocalValue上调用get()方法时,我们将获得请求线程的Integer值:

threadLocalValue.set(1);
Integer result = threadLocalValue.get();

有关更多信息,您可以看到When should I use a ThreadLocal variable?

答案 2 :(得分:1)

变量应始终在尽可能小的范围内声明,但ThreadLocal提供更大的范围,并且只应用于许多词法范围所需的变量。根据{{​​3}}:

  

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

因此,当您拥有公共代码并且希望基于每个线程保存状态时,可以使用它们。 doc:

中提供了一个示例
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();
     }
 }

在上面的示例中,类ThreadId生成唯一标识符,该标识符对于每个线程是本地的,在后续调用中不会更改。只要线程处于活动状态且ThreadLocal实例可访问,每个线程都会保存对其线程局部变量副本的隐式引用;在一个线程消失之后,它的所有线程局部实例副本都会被垃圾收集。

  

ThreadLocal变量如何降低创建昂贵的成本   对象

在某些基准测试支持此声明之前,我不确定最新JVM的情况如何。

答案 3 :(得分:0)

它不会降低创建实例的任何成本。您正在通过新的ThreadLocal()创建ThreadLocal的实例,当您使用myThreadLocal.put(&#34; anyString&#34;)时,它将一个String实例(已经存在)放入当前线程&#39 ; s threadLocals。