基于Android 7.0分析
關(guān)鍵的幾個(gè)點(diǎn)先列出來(lái)
public class ThreadLocal<T> {
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();
}
public void set(T value){
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if(map !=null ){
map.set(this, value);
}else{
createMap(t, value);
}
}
ThreadLocalMap getMap(Thread t){
return t.threadLocals;
}
void createMap(Thread t, T firstValue){
t.threadLocals = new ThreadLocalMap(this, firstValue);
}
}
可以看到核心了,ThreadLocal鏈接了Thread和ThreadLocalMap
public class Thread implements Runnable{
ThreadLocal.ThreadLocalMap threadLocals = null;
}
所以,ThreadLocal保存的數(shù)據(jù)是存在線程自身的成員變量ThreadLocal.ThreadLocalMap中的
//ThreadLocal.java
static class ThreadLocalMap{
static class Entry extends WeakReference<ThreadLocal>{
Object value;
Entry(ThreadLocal k, Object v){
super(k);
value = v;
}
}
private Entry[] table;
private Entry getEntry(ThreadLocal key){
int i = key.threadLocalHashCode & (table.length -1);
Entry e = table[I];
if(e!=null && e.get() ==key){
return e;
}
}
private void set(ThreadLocal key, Object value){
Entry[] tab = table;
int len = tab.length;
int i = key.threadLocalHashCode & (lend -1);
for(Entry e = tab[I],e!=null;e=tab[I = nexIndex(I,len)]){
ThreadLocal k = e.get();
if(k==key){
e.value = value;
return;
}
}
....
rehash();
}
}
那我們是怎么使用的呢,我們會(huì)先實(shí)例化一個(gè)ThreadLocal對(duì)象加酵,隨后在線程調(diào)用set(T) or get() @ThreadLocal方法。
從上面可以看出坟乾,每個(gè)線程都有一個(gè)ThreadLocal.ThreadLocalMap對(duì)象昧廷,其中又有一個(gè)數(shù)組Entry[],每次進(jìn)行set/get的時(shí)候窄锅,會(huì)將這個(gè)ThreadLocal作為key创千,保存在線程的ThreadLocal.ThreadLocalMap中,保存的過(guò)程是通過(guò)將ThreadLocal進(jìn)行hash取模保存在Entry[]中,如果發(fā)生了Hash沖突入偷,就取下一個(gè)點(diǎn)位
private static int nextIndex(int I, int len){
return ((I+1 > len)? I+1:0);
}
為了防止內(nèi)存泄漏追驴,Entry還繼承自WeakReference<ThreadLocal>