說(shuō)說(shuō)ThreadLocal的原理
Framework用到ThreadLocal的地方
Looper使用ThreadLocal
Choreographer使用ThreadLocal
如果當(dāng)前線程沒(méi)有Choreograhper對(duì)象的話,就會(huì)調(diào)用initialValue去初始一個(gè)Choreographer對(duì)象
ThreadLocal原理
每個(gè)線程里都有一個(gè)thread對(duì)象干像,這個(gè)對(duì)象里有一個(gè)數(shù)組table(類似HashMap)盖腕,
key:WeakReference<ThreadLocal>
value: Looper, Choreographer...
一個(gè)應(yīng)用里可以定義多個(gè)threadLocal谢谦,每個(gè)ThreadLocal都有自己的hash值
//每定義一個(gè)ThreadLocal都會(huì)初始一個(gè)hash值(遞增)
private?final?int?hash?=?hashCounter.getAndAdd(0x61c88647*2);
從threadLocals里查找ThreadLocal(key,value):
threadLocal index = threadLocal的hash%table.length
如果對(duì)于某個(gè)threadLocal窟绷,算出來(lái)的index已經(jīng)有值了脖咐,就從這個(gè)index開(kāi)始往后遍歷,找到空的位置拂酣,放進(jìn)去,然后返回這個(gè)空位置的index
ThreadLocal原理代碼解析
int index = hash & values.mask: 取余操作
this.reference == table[index]: 查看index位置上的key(weakReference) 是否和 當(dāng)前threadLocal對(duì)象的reference匹配上
return (T)table[index+1]: 返回threadLocal的value仲义,因?yàn)関alue是在key的下一個(gè)位置
這個(gè)方法很長(zhǎng)婶熬,但logic簡(jiǎn)單,就兩件事:
1. 通過(guò)threadLocal的initValue() 創(chuàng)建一個(gè)新的value
2. 在table里找一個(gè)合適的位置來(lái)存放key埃撵,value對(duì)
cleanUp():table里保存的key是threadLocal 的 weakReference赵颅,所以就有可能被回收掉,cleanUp方法就是清除已經(jīng)被回收掉的key暂刘,value對(duì)
說(shuō)說(shuō)ThreadLocal的原理
1. 同一個(gè)ThreadLocal對(duì)象饺谬,在不同線程get返回不同value
2. Thread對(duì)象里有張表(數(shù)組),保存了ThreadLocal對(duì)象的WeakReference到value的映射關(guān)系
3. 這張表(table)是怎么實(shí)現(xiàn)的谣拣?
數(shù)組結(jié)構(gòu)(table):[key, value, key, value, key, value, null, null, key, value, null, null,key value]
key: threadLocal對(duì)象的WeakReference
每個(gè)threadLocal對(duì)象有個(gè)hash值募寨,這個(gè)treadLocal對(duì)象在數(shù)組中的位置:index = hash % table, 如果index位置已經(jīng)有值了,就向后遍歷找到null的位置放入森缠,并返回后面這個(gè)的index
4. 是如何解決hash沖突的拔鹰?
????????上面已經(jīng)回答了