ThreadLocal
变量如何降低创建昂贵对象的成本?
例如:
private ThreadLocal<String> myThreadLocal = new ThreadLocal<String>();
在上面的一行中,我们创建了一个ThreadLocal对象,它将为thread创建一个对象。但是我无法理解如何降低创建实例的成本。
答案 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。