JAVA 中的引用
JAVA 中存在4種引用,由強到弱依次是強引用、軟引用、弱引用苞氮、虛引用。
- 強引用(Strong Reference):通常我們通過 new 創(chuàng)建一個對象的時候返回的引用就是強引用陨享。若一個對象通過一系列強引用是可達的葱淳,那么這個對象就是強可達的,它就不會被垃圾回收抛姑。
- 軟引用(Soft Reference):軟引用和弱引用的區(qū)別在于赞厕,若一個對象只是弱引用可達的,那么不論內存是否充足定硝,該對象都會被回收皿桑。然而若一個對象只是軟引用可達的,那么只有在內存不充足的時候該對象才會被回收蔬啡。因此軟引用要比弱引用要強一些诲侮。軟引用可以用來實現內存敏感的高速緩存。
軟引用在實際中有重要的應用箱蟆,例如瀏覽器的后退按鈕沟绪。按后退時,這個后退按鈕對應的網頁內容是重新進行請求還是從緩存中取出呢空猜?這就要看具體的實現策略了绽慈。
- 如果一個網頁在瀏覽結束時就進行內容的回收,則按后退查看前面瀏覽過的頁面時辈毯,需要重新請求構建坝疼。
- 如果將瀏覽過的網頁存儲到內存中可能會造成內存的大量浪費,甚至會造成內存溢出
這時候就可以使用軟引用谆沃。
Page prev = new Page(); // 獲取頁面進行瀏覽
SoftReference<Page> softRef = new SoftReference<Page>(prev); // 瀏覽完畢置為軟引用
if (softRef.get() != null) {
prev = softRef.get(); // 還沒有被垃圾收集器回收钝凶,直接獲取。
} else {
prev = new Page(); // 由于內存吃緊唁影,頁面已被回收耕陷,重新構建。
softRef = new SoftReference<Page>(prev); // 重新放進軟引用
}
- 弱引用(Weak Reference):弱引用對象的存在不會阻止它所指向的對象被垃圾回收据沈。假設垃圾收集器在某個時間點決定一個對象是弱可達的(weakly reachable)(也就是說當前指向它的全部都是弱引用)啃炸,這時垃圾收集器會清除所有指向該對象的弱引用,然后把這個對象標記為可終結(finalizable)的卓舵,這樣它隨后就會被回收。與此同時或稍后膀钠,垃圾收集器會把那些剛清除的弱引用放入引用隊列(Reference Queue掏湾,在創(chuàng)建弱引用對象時指定)中裹虫。
-
虛引用(Phantom Reference):虛引用是 JAVA 中最弱的引用,它弱到什么程度呢融击?它是如此弱筑公,以至于我們通過虛引用甚至無法獲取到被引用的對象,虛引用存在的唯一作用就是當它指向的對象被回收的時候尊浪,虛引用本身會被加入到引用隊列中匣屡,用作記錄它所指向的對象已被回收。虛引用與軟引用和弱引用的一個區(qū)別在于:虛引用必須和引用隊列 (ReferenceQueue)聯(lián)合使用拇涤。當垃圾回收器準備回收一個對象時捣作,如果發(fā)現它還有虛引用,就會在回收對象的內存之前鹅士,把這個虛引用加入到與之關聯(lián)的引用隊列中券躁。
虛引用主要用于跟蹤對象被垃圾回收的狀態(tài),通過查看引用隊列中是否包含對象所對應的虛引用來判斷它是否即將被垃圾回收掉盅,從而采取行動也拜,它并不被期待用來取得目標對象。Cleaner 就是一個虛引用的例子趾痘。
引用隊列
實際上慢哈,WeakReference 有兩個構造函數:
- WeakReference(T referent)
- WeakReference(T referent, ReferenceQueue<? super T> q)
我們可以看到第二個構造方法中提供了一個ReferenceQueue類型的參數,通過提供這個參數永票,我們便把創(chuàng)建的弱引用對象注冊到這個引用隊列上卵贱,這樣當該弱引用對象被垃圾回收器回收時,就會把它插入到引用隊列中瓦侮,我們便可以對這些被清除的弱引用對象進行統(tǒng)一管理(一般是做資源清除工作)艰赞。
WeakHashMap
WeakHashMap 內部是通過弱引用來管理 entry 的,弱引用的特性對應到 WeakHashMap 上意味著什么呢肚吏?將一對 <key,value> 放入到 WeakHashMap 里并不能避免該 key 值被 GC 回收方妖,除非在 WeakHashMap 之外還有對該key的強引用。
WeakHashMap的要點如下:
- 在 WeakHashMap 中罚攀,當某個鍵中的對象不再被正常使用時党觅,將自動移除該條目。更精確地說斋泄,對于一個給定的鍵杯瞻,其映射的存在并不阻止垃圾回收器對該鍵的丟棄,這就使該鍵成為可終止的炫掐,被終止魁莉,然后被回收。丟棄某個鍵時,其條目從映射中有效地移除旗唁。
- WeakHashMap 類的行為部分取決于垃圾回收器的動作畦浓。因為垃圾回收器在任何時候都可能丟棄鍵,WeakHashMap 就像是一個被悄悄移除條目的未知線程检疫。特別地讶请,即使對 WeakHashMap 實例進行同步,并且沒有調用任何賦值方法屎媳,在一段時間后 size 方法也可能返回較小的值夺溢,對于 isEmpty 方法,可能先返回 false烛谊,然后返回true风响,對于給定的鍵,containsKey 方法可能先返回 true 然后返回 false晒来,對于給定的鍵钞诡,get 方法可能先返回一個值,但接著返回 null湃崩,對于以前出現在映射中的鍵荧降,put 方法返回 null,而 remove 方法返回 false攒读,對于鍵集合朵诫、值集合和條目集合進行的檢查,生成的元素數量會越來越少薄扁。
- WeakHashMap 中的每個鍵對象間接地存儲為一個弱引用的指示對象剪返。因此,不管是在映射內還是在映射之外邓梅,只有在垃圾回收器清除某個鍵的弱引用之后脱盲,該鍵才會自動移除。
- 類似于大多數的集合類日缨,該類是并發(fā)不安全的钱反,如果想要使用并發(fā)安全版本的 WeakHashMap,使用Collections.synchronizedMap(weakHashMap) 進行同步即可匣距。
適用場景:
WeekHashMap 的這個特點特別適用于需要緩存的場景面哥。在緩存場景下,由于內存是有限的毅待,不能緩存所有對象尚卫;對象緩存命中可以提高系統(tǒng)效率,但緩存 MISS 也不會造成錯誤尸红,因為可以通過計算重新得到吱涉。