GuavaCache学习笔记二:Java四大引用类型回顾
前言
上一篇已經(jīng)講了,如何自己實(shí)現(xiàn)一個(gè)LRU算法。但是那種只是最基本的實(shí)現(xiàn)了LRU的剔除策略,并不能在生產(chǎn)中去使用。因?yàn)镚uava Cache中使用的是SoftReference去做的value實(shí)現(xiàn),所以有必要將Java的四種引用類型在復(fù)習(xí)一下。
備注:以下代碼使用的JVM配置為:
-Xmx128M -Xms64M -XX:+PrintGCDetails
Java的四種引用
強(qiáng)引用(StrongReference)
強(qiáng)引用是使用最普遍的引用。如果一個(gè)對(duì)象具有強(qiáng)引用,那垃圾回收器絕不會(huì)回收它。如下:
Object o=new Object(); // 強(qiáng)引用
當(dāng)內(nèi)存空間不足,Java虛擬機(jī)寧愿拋出OutOfMemoryError錯(cuò)誤,使程序異常終止,也不會(huì)靠隨意回收具有強(qiáng)引用的對(duì)象來解決內(nèi)存不足的問題。如果不使用時(shí),要通過如下方式來弱化引用,如下:
o=null; // 幫助垃圾收集器回收此對(duì)象
顯式地設(shè)置o為null,或超出對(duì)象的生命周期范圍,則gc認(rèn)為該對(duì)象不存在引用,這時(shí)就可以回收這個(gè)對(duì)象。具體什么時(shí)候收集這要取決于gc的算法。
軟引用 (SoftReference)
如果一個(gè)對(duì)象只具有軟引用,則內(nèi)存空間足夠,垃圾回收器就不會(huì)回收它;如果內(nèi)存空間不足了,就會(huì)回收這些對(duì)象的內(nèi)存。只要垃圾回收器沒有回收它,該對(duì)象就可以被程序使用。軟引用可用來實(shí)現(xiàn)內(nèi)存敏感的高速緩存。
看例子:
/*** @Description: 模擬Java四種引用類型的方法* @Author: wangmeng* @Date: 2018/12/8-11:10*/ public class ReferenceExample {public static void main(String[] args) throws Exception{/*** SoftReference:判斷JVM快要溢出的時(shí)候,JVM GC時(shí)會(huì)判斷有沒有SoftReference數(shù)據(jù)*/int counter = 0;List<SoftReference<Ref>> container = Lists.newArrayList();for (;;) {int current = counter++;container.add(new SoftReference<>(new Ref(current)));System.out.println("The " + current + " Ref will be insert into container");TimeUnit.MILLISECONDS.sleep(50);}private static class Ref {//調(diào)用Ref的時(shí)候,每次都new出來一個(gè)lM的byte,模擬觸發(fā)GCprivate byte[] data = new byte[1024 * 1024];private final int index;private Ref(int index) {this.index = index;}@Overrideprotected void finalize() throws Throwable {System.out.println("The index [" + index + "] will be GC.");}} }
可以看到上面的輸出結(jié)果,到了后面仍然OOM了,因?yàn)槲覀冞@里設(shè)置的執(zhí)行時(shí)間是50ms,雖然內(nèi)存不足時(shí)進(jìn)行了GC操作,但是由于放入的速度過快,所以還是OOM了。
這里要展示的是,當(dāng)內(nèi)存不足的時(shí)候,垃圾回收就會(huì)回收軟引用的內(nèi)容來防止OOM,但是這樣并不能百分百避免OOM。
弱引用(WeakReference)
弱引用與軟引用的區(qū)別在于:只具有弱引用的對(duì)象擁有更短暫的生命周期。在垃圾回收器線程掃描它所管轄的內(nèi)存區(qū)域的過程中,一旦發(fā)現(xiàn)了只具有弱引用的對(duì)象,不管當(dāng)前內(nèi)存空間足夠與否,都會(huì)回收它的內(nèi)存。不過,由于垃圾回收器是一個(gè)優(yōu)先級(jí)很低的線程,因此不一定會(huì)很快發(fā)現(xiàn)那些只具有弱引用的對(duì)象。
弱引用可以和一個(gè)引用隊(duì)列(ReferenceQueue)聯(lián)合使用,如果弱引用所引用的對(duì)象被垃圾回收,Java虛擬機(jī)就會(huì)把這個(gè)弱引用加入到與之關(guān)聯(lián)的引用隊(duì)列中。當(dāng)你想引用一個(gè)對(duì)象,但是這個(gè)對(duì)象有自己的生命周期,你不想介入這個(gè)對(duì)象的生命周期,這時(shí)候你就是用弱引用。這個(gè)引用不會(huì)在對(duì)象的垃圾回收判斷中產(chǎn)生任何附加的影響。
執(zhí)行結(jié)果如圖,可見在GC運(yùn)行時(shí)必定會(huì)對(duì)弱引用進(jìn)行回收。
虛引用(PhantomReference)
“虛引用”顧名思義,就是形同虛設(shè),與其他幾種引用都不同,虛引用并不會(huì)決定對(duì)象的生命周期。如果一個(gè)對(duì)象僅持有虛引用,那么它就和沒有任何引用一樣,在任何時(shí)候都可能被垃圾回收器回收。
虛引用主要用來跟蹤對(duì)象被垃圾回收器回收的活動(dòng)。虛引用與軟引用和弱引用的一個(gè)區(qū)別在于:虛引用必須和引用隊(duì)列 (ReferenceQueue)聯(lián)合使用。當(dāng)垃圾回收器準(zhǔn)備回收一個(gè)對(duì)象時(shí),如果發(fā)現(xiàn)它還有虛引用,就會(huì)在回收對(duì)象的內(nèi)存之前,把這個(gè)虛引用加入到與之 關(guān)聯(lián)的引用隊(duì)列中。
使用jconsole,點(diǎn)擊執(zhí)行GC,這時(shí)可以看到其實(shí)打印了PhantomReference中的數(shù)據(jù)。
總結(jié)
以上代碼在我的github可以看到:
我的github地址
可參見cn.barrywangmeng.cache.reference.ReferenceExample
來自為知筆記(Wiz)
轉(zhuǎn)載于:https://www.cnblogs.com/wang-meng/p/20bcc1ea5a9822fe3398531594062068.html
總結(jié)
以上是生活随笔為你收集整理的GuavaCache学习笔记二:Java四大引用类型回顾的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: go——工程结构
- 下一篇: Java语言基础22--访问权限