Thread.currentThread.map當(dāng)前線程的map
map的key是ThreadLocal的實(shí)例
當(dāng)ThreadLocal被回收時(shí),其key為null,但value可能泄露與內(nèi)存所以采用弱引用
ThreadLocal的map的Entry為什么采用弱引用
防止內(nèi)存泄漏,tl本身為null時(shí),無(wú)法及時(shí)回收key為null的value
key 使用弱引用:引用的ThreadLocal的對(duì)象被回收了柱衔,由于ThreadLocalMap持有ThreadLocal的弱引用街佑,即使沒(méi)有手動(dòng)刪除,ThreadLocal也會(huì)被回收盾舌。value在下一次ThreadLocalMap調(diào)用set,get,remove的時(shí)候會(huì)被清除
ThreadLocal用途
聲明式識(shí)事務(wù)
ThreadLocal原理
每個(gè)Thread 維護(hù)一個(gè) ThreadLocalMap 映射表汹押,這個(gè)映射表的 key 是 ThreadLocal實(shí)例本身矿筝,value 是真正需要存儲(chǔ)的 Object
ThreadLocal 本身并不存儲(chǔ)值,它只是作為一個(gè) key 來(lái)讓線程從 ThreadLocalMap 獲取 value
ThreadLocalMap 是使用 ThreadLocal 的弱引用作為 Key 的棚贾,弱引用的對(duì)象在 GC 時(shí)會(huì)被回收
ThreadLocal導(dǎo)致內(nèi)存泄露
ThreadLocalMap的生命周期跟Thread一樣長(zhǎng)
ThreadLocalMap使用ThreadLocal的弱引用作為key窖维,
如果一個(gè)ThreadLocal沒(méi)有外部強(qiáng)引用來(lái)引用它,那么系統(tǒng) GC 的時(shí)候妙痹,
這個(gè)ThreadLocal勢(shì)必會(huì)被回收铸史,這樣一來(lái),ThreadLocalMap中就會(huì)出現(xiàn)key為null的
Entry怯伊,就沒(méi)有辦法訪問(wèn)這些key為null的Entry的value琳轿,如果當(dāng)前線程再遲遲不結(jié)束的話(線程池重用線程),
這些key為null的Entry的value就會(huì)一直存在一條強(qiáng)引用鏈:
Thread Ref -> Thread -> ThreaLocalMap -> Entry -> value永遠(yuǎn)無(wú)法回收耿芹,
造成內(nèi)存泄漏崭篡。
ThreadLocal的措施
get(),set(),remove()的時(shí)候都會(huì)清除線程ThreadLocalMap里所有key為null的value
但無(wú)法保證
static的ThreadLocal,延長(zhǎng)了ThreadLocal的生命周期吧秕,可能導(dǎo)致的內(nèi)存泄漏
分配使用了ThreadLocal又不再調(diào)用get(),set(),remove()方法琉闪,那么就會(huì)導(dǎo)致內(nèi)存泄漏
ThreadLocal最佳實(shí)踐
每次使用完ThreadLocal,都調(diào)用它的remove()方法砸彬,清除數(shù)據(jù)
在使用線程池的情況下颠毙,沒(méi)有及時(shí)清理ThreadLocal,不僅是內(nèi)存泄漏的問(wèn)題砂碉,更嚴(yán)重的是可能導(dǎo)致業(yè)務(wù)邏輯出現(xiàn)問(wèn)題蛀蜜。所以,使用ThreadLocal就跟加鎖完要解鎖一樣增蹭,用完就清理