一磕仅、ThreadLocal
1珊豹、作用:使用ThreadLocal來做線程級(jí)的緩存,因?yàn)楦鱾€(gè)線程使用ThreadLocal中的數(shù)據(jù)是互不影響的榕订,不存在數(shù)據(jù)安全的問題店茶。
2、初始化步驟
1)在ThreadLocalMap中定位到ThreadLocal為key的entry項(xiàng)劫恒;
2)? 如果存在entry項(xiàng)贩幻,同時(shí)存在key轿腺,則直接用新的value替換掉舊的value;
3)如果存在entry項(xiàng)丛楚,同時(shí)key為空族壳,那么就恢復(fù)key的值和重新設(shè)置value;
4)如果不存在entry趣些,則創(chuàng)建一個(gè)新的entry項(xiàng)仿荆。
需要說明的是,在進(jìn)行set操作時(shí)喧务,當(dāng)ThreadLocal被設(shè)置為null時(shí)赖歌,ThreadLocalMap就會(huì)移除key為ThreadLocal的Entry(因?yàn)镋ntry本身就是一個(gè)弱引用對(duì)象)。
3功茴、ThreadLocal內(nèi)存泄漏的原因
?可以看出庐冯,ThreadLocalMap中的key是弱引用類型。Java進(jìn)行垃圾回收時(shí)坎穿,會(huì)一直回收掉弱引用類型的對(duì)象展父。在代碼實(shí)例中,key即ThreadLocal對(duì)象是弱引用類型玲昧,當(dāng)沒有強(qiáng)引用指向ThreadLocal對(duì)象時(shí)栖茉,gc會(huì)回收掉Entry中的key,即回收ThreadLocal對(duì)象本身孵延。而value不會(huì)被回收掉的吕漂,因?yàn)関alue是強(qiáng)引用。Entry對(duì)象是位于ThreadLocal對(duì)象內(nèi)的尘应,既然ThreadLocal對(duì)象已經(jīng)被回收掉了惶凝,entry就成了一個(gè)引用不可達(dá)的對(duì)象,gc無法回收犬钢,所以會(huì)出現(xiàn)內(nèi)存泄露苍鲜。
為了避免這個(gè)問題,可以先調(diào)用ThreadLocal的remove的方法玷犹,以便清除掉不需要的value混滔。
4、使用場(chǎng)景
NamedThreadLocal:RequestContextHolder歹颓、TransactionSynchronizationManager坯屿、LocaleContextHolder、SimpleDateFormat等的共享應(yīng)用