所谓ThreadLocal,就是每个线程人手一只笔,线程本地存储。
1、使用
ThreadLocal的常规用法是get和set方法,比如可能这样用
static ThreadLocal<Object> tlObj = new ThreadLocal<>();
//如下使用方法
if(tlObj .get() == null){
tlObj .set(new Object());
}
ThreadLocal的使用时在应用层面(即代码层面)自己来实现相关的控制。
2、原理
Thread有个内部有个ThreadLocalMap的变量,是一个用来存储本线程的ThreadLocal值的Map。
//Thread.java
ThreadLocal.ThreadLocalMap threadLocals = null;
下面来看下,我们代码中的get和set方法如何实现。
get方法,实现如下。
//ThreadLocal.java
public T get() {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null) {
ThreadLocalMap.Entry e = map.getEntry(this);
if (e != null) {
@SuppressWarnings("unchecked")
T result = (T)e.value;
return result;
}
}
return setInitialValue();
}
其中,getMap方法如下,即返回线程的threadLocals变量
//ThreadLocal.java
ThreadLocalMap getMap(Thread t) {
return t.threadLocals;
}
get方法的核心就是在当前Thread的threadLocals中寻找以当前ThreadLocal对象为Key存储的T。
再来看看set方法:
//ThreadLocal.java
public void set(T value) {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null)
map.set(this, value);
else
createMap(t, value);
}
完全跟get相反的操作,即在当前线程变量Thread的threadLocals中以当前ThreadLocal对象为key存储ThreadLocal的泛型T。
3、再深入一点
Thread对象中的threadLocals是一个ThreadLocalMap,它的每一个Entry结构如下
static class Entry extends WeakReference<ThreadLocal<?>> {
Object value;
Entry(ThreadLocal<?> k, Object v) {
super(k);
value = v;
}
}
这是一个弱引用,所谓弱引用,即不影响java虚拟机进行垃圾回收的引用。如果ThreadLocal的强引用被回收后,ThreadLocalMap的key就会变为null,这样系统在ThreadLocalMap清理时,会将这些垃圾数据回收(执行时机不确定)。在线程退出时,会做如下操作。
//Thread.java
private void exit() {
//省略
threadLocals = null;
//省略
}
将threadLocals置空,会加速threadLocals的回收。
另外,如果需要父子线程进行数据的传递,还有一种做法是使用InheritableThreadLocal。
在线程创建时,会将父线程的该部分进行浅拷贝(即引用赋值),所以注意,如果子线程直接修改了引用,父线程是感知不到的,如果是修改了引用的对象内部的值,父线程还是能感知到的。
//Thread.java
//这东西其实就是InheritableThreadLocal的Map,专门用来实现父子线程之间的传递
ThreadLocal.ThreadLocalMap inheritableThreadLocals = null;
//线程初始化时做了如下动作
private void init(
//此处省略一群变量
if (parent.inheritableThreadLocals != null)
this.inheritableThreadLocals =
//继承它老爹的家产,浅拷贝
ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);
就酱,继承遗产这货,还是不再展开了,还有GC也不细讲,都以后展开。