【java之juc并发包系列教程】一文看懂ThreadLocal底层实现
文章目录
- 前言
- 一、ThreadLocal是什么?
- 二、ThreadLocal对象
-
- 先看看new ThreadLocal()
- threadLocal.set(T value)方法
- threadLocal.get()方法
- 到这里其实原理已经明了了,并且也不难看出ThreadLocal只能是一个线程中设置和获取值,对于子线程是获取不到父线程的值的
前言
一、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 assignedprivate static final AtomicInteger nextId = new AtomicInteger(0); // Thread local variable containing each thread's IDprivate 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 necessarypublic static int get() { return threadId.get();} }
只要线程处于活动状态并且 ThreadLocal 实例是可访问的,每个线程都持有对其线程局部变量副本的隐式引用;在线程消失后,它的所有线程本地实例副本都将受到垃圾回收(除非存在对这些副本的其他引用)。自:1.2 作者:Josh Bloch 和 Doug Lea
二、ThreadLocal对象
简单使用其实就是new出对象,然后get和set方法
先看看new ThreadLocal()
初始化就new了对象其他什么都没干
threadLocal.set(T value)方法
//将此线程局部变量的当前线程副本设置为指定值。大多数子类不需要重写此方法,仅依靠 initialValue 方法来设置线程局部变量的值。//参数://value – 要存储在此线程本地的当前线程副本中的值。 public void set(T value) { Thread t = Thread.currentThread();//获取当前线程对象 ThreadLocalMap map = getMap(t); //调用本地getMap方法返回ThreadLocalMap if (map != null) {//如果ThreadLocalMap不为空就设置值,key为threadLocal对象本身 map.set(this, value); } else {//如果ThreadLocalMap为空,就创建ThreadLocalMap并赋值 createMap(t, value); } }
关于ThreadLocalMap介绍可以看这篇文章,这里先不多介绍,用法类似于Maphttps://blog.csdn.net/zt011052/article/details/90055586
我们进入getMap方法看看
返回了线程对象threadLocals属性,看Thread源码
说明Thread对象本身持有了ThreadLocalMap类型的对象,只有ThreadLocal初次赋值时候才会实例化
所以我们在查看threadLocal.createMap(t, value);方法
原来这里就是创建ThreadLocalMap对象并赋值给Thread的threadLocals属性
threadLocal.get()方法
public T get() { Thread t = Thread.currentThread(); //获取当前线程 ThreadLocalMap map = getMap(t);//获取当前线程持有的ThreadLocalMap对象 if (map != null) { ThreadLocalMap.Entry e = map.getEntry(this); //通过key也就是threadLocal来获取值 if (e != null) { @SuppressWarnings("unchecked") T result = (T)e.value; return result; } } //没有获取到就设置初始化值并返回 return setInitialValue(); }
setInitialValue()方法
private T setInitialValue() { T value = initialValue();//获取初始化值,在这里其实就是返回null Thread t = Thread.currentThread(); ThreadLocalMap map = getMap(t); if (map != null) { map.set(this, value); } else { createMap(t, value); } if (this instanceof TerminatingThreadLocal) { TerminatingThreadLocal.register((TerminatingThreadLocal<?>) this); } return value; }