所謂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也不細講,都以後展開。