文章目录
前言
一、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 实例是可访问的,每个线程都持有对其线程局部变量副本的隐式引用;在线程消失后,它的所有线程本地实例副本都将受到垃圾回收(除非存在对这些副本的其他引用)。自: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;
}