ThreadLocal是一個線程內(nèi)部的數(shù)據(jù)存儲類,通過它可以在指定的線程中存儲數(shù)據(jù),數(shù)據(jù)存儲以后,只有在指定線程中可以獲取到存儲的數(shù)據(jù),對于其它線程來說無法獲取到數(shù)據(jù)。一般來說,當(dāng)某些數(shù)據(jù)是以線程為作用域并且不同線程具有不同的數(shù)據(jù)副本的時候,就可以考慮采用ThreadLocal。比如對于Handler來說,它需要獲取當(dāng)前線程的Looper,很顯然Looper的作用域就是線程并且不同線程具有不同的Looper,這個時候通過ThreadLocal就可以輕松實現(xiàn)Looper在線程中的存取,如果不采用ThreadLocal,那么系統(tǒng)就必須提供一個全局的哈希表供Handler查找指定線程的Looper,這樣一來就必須提供一個類似于LooperManager的類了,但是系統(tǒng)并沒有這么做而是選擇了ThreadLocal,這就是ThreadLocal的好處。
ThreadLocal的存值:
public void set(T value) {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null)
map.set(this, value);
else
createMap(t, value);
}
/**
* Create the map associated with a ThreadLocal. Overridden in
* InheritableThreadLocal.
*
* @param t the current thread
* @param firstValue value for the initial entry of the map
* @param map the map to store.
*/
void createMap(Thread t, T firstValue) {
t.threadLocals = new ThreadLocalMap(this, firstValue);
}
ThreadLocal的set方法就是按照線程進行存值的:
首先獲取當(dāng)前線程,然后根據(jù)該線程獲得對應(yīng)線程中用于存放數(shù)據(jù)的map。
如果map不為空就將value值存放到map中。
如果map為空,就去創(chuàng)建一個該線程對應(yīng)的map。
ThreadLocal的取值:
public T get() {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null) {
ThreadLocalMap.Entry e = map.getEntry(this);
if (e != null)
return (T)e.value;
}
return setInitialValue();
}
private T setInitialValue() {
T value = initialValue();
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null)
map.set(this, value);
else
createMap(t, value);
return value;
}
protected T initialValue() {
return null;
}
ThreadLocal的取值過程如下:
首先拿到當(dāng)前的線程,然后得到當(dāng)前線程對應(yīng)的map。
如果map不為空就從map里面取值。
如果map為空,就返回初始值。(可以重寫initialValue()方法,修改初始值)
結(jié)合Handler中Looper的獲取和存儲可以更加清晰的了解ThreadLocal。
http://www.itdecent.cn/p/f5e0a87853ac