软引用和弱引用的区别_强、软、弱、虚引用的区别和使用
原文閱讀:
強(qiáng)、軟、弱、虛引用的區(qū)別和使用?mp.weixin.qq.comJava提供了四種級別的應(yīng)用類型:強(qiáng)引用、軟引用、弱引用及虛引用。那么這四種引用類型有什么區(qū)別呢?
首先我們通過一張圖來看看四種引用在Java中的表示:
FinalReference
由于FinalReference是包內(nèi)可見,Finalizer是其唯一的擴(kuò)展類。在外部是無法直接使用這兩個類的,因?yàn)镕inalReference引用類型是為JVM提供的,JVM會對那些實(shí)現(xiàn)了 Object 中 finalize() 方法的類實(shí)例化一個對應(yīng)的FinalReference,提供 對象被 GC 前需要執(zhí)行 finalize 方法的對象 的機(jī)制。這里不詳細(xì)介紹。
強(qiáng)引用(StrongReference)
強(qiáng)引用在 java.lang.ref 中并沒有實(shí)際的對應(yīng)類型,但我們程序中幾乎所有的引用使用的都是強(qiáng)引用。
StringBuilder sb = new StringBuilder();上面通過在堆中創(chuàng)建實(shí)例,然后賦值給棧中局部變量 sb 的方式 就是 強(qiáng)引用。
強(qiáng)引用有如下特點(diǎn):
- 強(qiáng)引用可以直接訪問目標(biāo)對象
- 強(qiáng)引用(存在)指向的對象任何時候都不會被回收,JVM寧愿拋出OOM異常,也不會回收。
- 強(qiáng)引用可能會導(dǎo)致內(nèi)存泄漏
注意: 為了盡量避免內(nèi)存不足的情況,我們可以在變量sb使用后通過顯示的將變量sb置為null,來加速對象的回收。
解釋: 1. 內(nèi)存溢出(out of memory) 是指 程序在申請內(nèi)存時,沒有足夠的內(nèi)存空間供其使用,出現(xiàn) out of memory.
軟引用(SoftReference)
軟引用對應(yīng)的類為 java.lang.ref.SoftReference, 一個軟引用中的對象,不會很快被JVM回收,JVM會根據(jù)當(dāng)前堆的使用情況來判斷何時回收,當(dāng)堆的使用率超過閾值時,才回去回收軟引用中的對象。
先通過一個例子來了解一下軟引用:
Object obj = new Object(); SoftReference softRef = new SoftReference<Object>(obj); //刪除強(qiáng)引用 obj = null; //調(diào)用gc System.gc(); System.out.println("gc之后的值:" + softRef.get()); // 對象依然存在軟引用也可以和一個引用隊(duì)列聯(lián)合使用,如果軟引用中的對象(obj)被回收,那么軟引用會被 JVM 加入關(guān)聯(lián)的引用隊(duì)列中。
ReferenceQueue<Object> queue = new ReferenceQueue<>(); Object obj = new Object(); SoftReference softRef = new SoftReference<Object>(obj,queue); //刪除強(qiáng)引用 obj = null; //調(diào)用gc System.gc(); System.out.println("gc之后的值: " + softRef.get()); // 對象依然存在 //申請較大內(nèi)存使內(nèi)存空間使用率達(dá)到閾值,強(qiáng)迫gc byte[] bytes = new byte[100 * 1024 * 1024]; //如果obj被回收,則軟引用會進(jìn)入引用隊(duì)列 Reference<?> reference = queue.remove(); if (reference != null){System.out.println("對象已被回收: "+ reference.get()); // 對象為null }引用隊(duì)列(ReferenceQueue)作用
Queue的意義在于我們在外部可以對queue中的引用進(jìn)行監(jiān)控,當(dāng)引用中的對象被回收后,我們可以對引用對象本身繼續(xù)做一些清理操作,因?yàn)槲覀円脤ο?#xff08;softRef)也占有一定的資源。
弱引用(WeakReference)
弱引用中的對象具有很短的聲明周期,因?yàn)樵谙到y(tǒng)GC時,只要發(fā)現(xiàn)弱引用,不管堆空間是否足夠,都會將對象進(jìn)行回收。由于垃圾回收器是一個優(yōu)先級很低的線程,因此不一定會很快發(fā)現(xiàn)那些只具有弱引用的對象。
弱引用的簡單使用:
Object obj = new Object(); WeakReference weakRef = new WeakReference<Object>(obj); //刪除強(qiáng)引用 obj = null; System.out.println("gc之后的值:" + weakRef.get()); // 對象依然存在 //調(diào)用gc System.gc(); System.out.println("gc之后的值:" + weakRef.get()); // 對象為null弱引用也可以和一個引用隊(duì)列聯(lián)合使用,如果弱引用中的對象(obj)被回收,那么軟引用會被 JVM 加入關(guān)聯(lián)的引用隊(duì)列中。
ReferenceQueue<Object> queue = new ReferenceQueue<>(); Object obj = new Object(); WeakReference weakRef = new WeakReference<Object>(obj,queue); //刪除強(qiáng)引用 obj = null; System.out.println("gc之后的值: " + weakRef.get()); // 對象依然存在 //調(diào)用gc System.gc(); //如果obj被回收,則軟引用會進(jìn)入引用隊(duì)列 Reference<?> reference = queue.remove(); if (reference != null){System.out.println("對象已被回收: "+ reference.get()); // 對象為null }軟引用和弱引用都非常適合保存那些可有可無的緩存數(shù)據(jù),當(dāng)內(nèi)存不足時,緩存數(shù)據(jù)被回收(再通過備選方案查詢),當(dāng)內(nèi)存充足時,也可以存在較長時間,起到加速的作用。應(yīng)用
- WeakHashMap
當(dāng)key只有弱引用時,GC發(fā)現(xiàn)后會自動清理鍵和值,作為簡單的緩存表解決方案。
- ThreadLocal
ThreadLocal.ThreadLocalMap.Entry 繼承了弱引用,key為當(dāng)前線程實(shí)例,和WeakHashMap基本相同。
虛引用(PhantomReference)
虛引用 就是 形同虛設(shè) ,它并不能決定 對象的生命周期。任何時候這個只有虛引用的對象都有可能被回收。因此,虛引用主要用來跟蹤對象的回收,清理被銷毀對象的相關(guān)資源。PhantomReference的 get() 方法永遠(yuǎn)返回null ,而且只提供了與引用隊(duì)列同用的構(gòu)造函數(shù)。所以虛引用必須和引用隊(duì)列一同使用。
Map<Object, String> map = new HashMap<>(); ReferenceQueue<Object> queue = new ReferenceQueue<>(); Object obj = new Object(); PhantomReference phantomRef = new PhantomReference<Object>(obj,queue); map.put(obj,"obj val"); new CheckRefQueue(queue,map).start(); //刪除強(qiáng)引用 obj = null; Thread.sleep(1000); int i = 1; while (true){System.out.println("第"+i+"次gc");System.gc();Thread.sleep(1000); } public class CheckRefQueue extends Thread {private ReferenceQueue queue;private Map<Object, String> map;public CheckRefQueue(ReferenceQueue queue, Map<Object, String> map) {this.queue = queue;this.map = map;}@Overridepublic void run() {// 等待,直到對象唄回收Reference reference = queue.remove();// 釋放引用對象的引用map.remove(reference.get());} }總結(jié)
總結(jié)
以上是生活随笔為你收集整理的软引用和弱引用的区别_强、软、弱、虚引用的区别和使用的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【LeetCode笔记】剑指 Offer
- 下一篇: 产生复选框的html,html根据复选框