天天看點

面試官:你說一說ThreadLocal記憶體洩漏問題以及怎麼解決

關于Thread、ThreadLocal、ThreadLocalMap他們三個之間的差別:

一個Thread中隻有一個ThreadLocalMap,一個ThreadLocalMap中可以有多個ThreadLocal對象,其中一個ThreadLocal對象對應一個ThreadLocalMap中的一個Entry(也就是說:一個Thread可以依附有多個ThreadLocal對象)。

面試官:你說一說ThreadLocal記憶體洩漏問題以及怎麼解決

什麼是記憶體洩漏

記憶體洩漏是由于疏忽或者錯誤未能釋放已經不再使用的記憶體

四種引用

1、強引用

強引用是最傳統的“引用”的定義,是指在程式代碼之中普遍存在的引用指派,即類似“Object obj=new Object()”這種引用關系。無論任何情況下,隻要強引用關系還存在,垃圾收集器就永遠不會回收掉被引用的對象。

2、軟引用

軟引用是用來描述一些還有用,但非必須的對象。隻被軟引用關聯着的對象,在系統将要發生記憶體溢出異常前,會把這些對象列進回收範圍之中進行第二次回收,如果這次回收還沒有足夠的記憶體,才會抛出記憶體溢出異常。在JDK 1.2版之後提供了SoftReference類來實作軟引用。

應用:緩存。

3、弱引用

弱引用也是用來描述那些非必須對象,但是它的強度比軟引用更弱一些,被弱引用關聯的對象隻能生存到下一次垃圾收集發生為止。當垃圾收集器開始工作,無論目前記憶體是否足夠,都會回收掉隻被弱引用關聯的對象。在JDK 1.2版之後提供了WeakReference類來實作弱引用。

應用:ThreadLocal;WeakHashMap。

4、虛引用

虛引用也稱為“幽靈引用”或者“幻影引用”,它是最弱的一種引用關系。一個對象是否有虛引用的存在,完全不會對其生存時間構成影響,也無法通過虛引用來取得一個對象執行個體。為一個對象設定虛引用關聯的唯一目的隻是為了能在這個對象被收集器回收時收到一個系統通知。在JDK 1.2版之後提供了PhantomReference類來實作虛引用。

應用:在jvm中,用來管理直接記憶體(例如NIO中ByteBuffer申請直接記憶體allocateDirect)的回收.會将虛引用的回收時間添加到一個隊列中。通過檢測虛引用可以做一些善後操作。

Threadlocal記憶體洩漏

每個線程都有一個自己的ThreadLocalMap,是線程獨有的,别的線程無法通路到你所在的線程的ThreadLocalMap,ThreadLocalMap是entry結構的,他的key(是Threadlocal對象)是弱引用, 當不存在外部強引用的時候,在垃圾回收的時候會随時被回收,但是他的value是強引用,強引用鍊是Thread->ThreadLocalMap->entry->value。可以知道,隻有當Thread被回收的時候,這個value才有機會被垃圾回收,否則,隻要線程不退出,value就沒有被回收的機會。這是導緻ThreadLocal記憶體洩漏的原因。解決辦法是在ThreadLocalMap進行set(),get(),remove()的時候都會自己清理,最好的做法還是不用了就remove()掉。