欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

詳解Java中的四種引用類型(強(qiáng)軟弱虛)

 更新時間:2023年10月25日 11:12:24   作者:閑不住的碼  
Java中的引用類型主要分為四種,分別是強(qiáng)引用、軟引用、弱引用和虛引用,這篇文章主要為大家詳細(xì)介紹了四者的使用與區(qū)別,需要的小伙伴可以參考下

強(qiáng)引用(StrongReference)

強(qiáng)引用指的就是代碼中普遍存在的賦值方式,比如A a = new A()這種。強(qiáng)引用關(guān)聯(lián)的對象,永遠(yuǎn)不會被GC回收。

當(dāng)內(nèi)存空間不足的時候,java虛擬機(jī)寧愿拋出OutOfMemoryError 錯誤,是程序異常終止,也不會回收具有強(qiáng)引用的對象來解決內(nèi)存不足的問題

obj=null //幫助垃圾回收器回收這個對象

顯式地設(shè)置obj為null,或者說超出對象的生命周期范圍,則GC認(rèn)為該對象不存在引用,這時候就可以回收這個對象了,具體什么時候回收這要看GC的算法是怎么樣的。

當(dāng)一個方法的內(nèi)部有一個強(qiáng)引用,這個引用保存在棧中,而這個引用的內(nèi)容存放在堆中,當(dāng)這個方法運(yùn)行完成后就會退出方法棧,那么引用內(nèi)容也會跟著就會不存在了,這個Object就會被回收。但是如果個這個obj是一個全局變量的時候,就需要再不用的時候?qū)①x值為null,因?yàn)閺?qiáng)引用是不會被垃圾回收的

在ArrayList的clear方法中就用到了強(qiáng)引用

private transient Object[] elementData;
 
public void clear() {
    modCount++;
     // clear to let GC do its work
    for (int i = 0; i < size; i++) {
        elementData[i] = null;
    }
    size = 0;
}

在 ArrayList 類中定義了一個私有的變量 elementData 數(shù)組,在調(diào)用方法清空數(shù)組時可以看到為每個數(shù)組內(nèi)容賦值為null。 不同于elementData = null,強(qiáng)引用仍然存在,避免在后續(xù)調(diào)用 add()等方法添加元素時,進(jìn)行重新的內(nèi)存分配。使用如 clear() 方法中釋放內(nèi)存的方法對數(shù)組中存放的引用類型特別適用,這樣就可以及時釋放內(nèi)存。

軟引用(SoftReference)

軟引用可以用SoftReference來描述,指的是那些有用但是不是必須要的對象。系統(tǒng)在發(fā)生內(nèi)存溢出前會對這類引用的對象進(jìn)行回收。

軟引用可以用來實(shí)現(xiàn)內(nèi)存敏感的高速緩存

軟引用自身不會被垃圾回收,因?yàn)镚C Root還引用著,軟引用自身需要配合引用隊(duì)列來釋放。

String str = new String("abc"); // 強(qiáng)引用
SoftReference<String> softRef = new SoftReference<String>(str); // 軟引用  
// 當(dāng)內(nèi)存不足時,等價于:
if (JVM.內(nèi)存不足()) {//當(dāng)內(nèi)存不夠的時候就回收
   str = null;  // 轉(zhuǎn)換為軟引用
   System.gc(); // 垃圾回收器進(jìn)行回收
}

軟引用在實(shí)際中有重要的應(yīng)用:

瀏覽器的后退按鈕。按后退時,這個后退時顯示的網(wǎng)頁內(nèi)容是重新進(jìn)行請求還是從緩存中取出呢?這就要看具體的實(shí)現(xiàn)策略了。

  • 獲取頁面進(jìn)行瀏覽,瀏覽完成后就可以將頁面設(shè)置為軟應(yīng)用
  • 當(dāng)點(diǎn)擊回退按鈕到先前瀏覽過的頁面后,判斷是否被垃圾回收機(jī)制回收了,沒有回收就直接用,如果回收了,就在重新構(gòu)建頁面

軟引用可以和一個引用隊(duì)列(ReferenceQueue)聯(lián)合使用,當(dāng)引用的對象被垃圾回收器回收后,JVM會自動把這個軟引用加入到和它相關(guān)的這個引用隊(duì)列中

弱引用(WeakReference)

弱引用可以用WeakReference來描述,他的強(qiáng)度比軟引用更低一點(diǎn),弱引用的對象下一次GC的時候一定會被回收,而不管內(nèi)存是否足夠。 不過,由于垃圾回收器是一個優(yōu)先級很低的線程,因此不一定會很快發(fā)現(xiàn)那些只具有弱引用的對象。

弱引用與軟引用的區(qū)別在于:只具有弱引用的對象擁有更短暫的生命周期。

String str = new String("abc"); //強(qiáng)引用
WeakReference<String> weakRef = new WeakReference<String>(str); // 弱引用
str = null;
 
// 當(dāng)垃圾回收器進(jìn)行掃描回收時等價于:
str = null;
System.gc(); // 垃圾回收器進(jìn)行回收
 
// 下面的代碼會讓str再次變?yōu)橐粋€強(qiáng)引用:
str = weakRef.get();

使用場景:

  • 如果這個對象是偶爾的使用,并且希望在使用時隨時就能獲取到,但又不想影響此對象的垃圾收集,那么你應(yīng)該用弱引用來記住此對象。
  • 當(dāng)你想引用一個對象,但是這個對象有自己的生命周期,你不想介入這個對象的生命周期,這時候你就可以使用弱引用。這個引用不會在對象的垃圾回收判斷中產(chǎn)生任何附加的影響。

弱引用可以和一個引用隊(duì)列(ReferenceQueue)聯(lián)合使用,如果弱引用所引用的對象被垃圾回收,Java虛擬機(jī)就會把這個弱引用加入到與之關(guān)聯(lián)的引用隊(duì)列中。

虛引用(PhantomReference)

虛引用也被稱作幻影引用,是最弱的引用關(guān)系,可以用PhantomReference來描述,他必須和ReferenceQueue一起使用,同樣的當(dāng)發(fā)生GC的時候,虛引用也會被回收。

虛引用與其他幾種引用都不同,它并不會決定對象的生命周期。如果一個對象僅持有虛引用,那么它就和沒有任何引用一樣,在任何時候都可能被垃圾回收器回收。

虛引用與軟引用和弱引用的一個區(qū)別在于: 虛引用必須和引用隊(duì)列 (ReferenceQueue)聯(lián)合使用。當(dāng)垃圾回收器準(zhǔn)備回收一個對象時,如果發(fā)現(xiàn)它還有虛引用,就會在回收對象的內(nèi)存之前,把這個虛引用加入到與之關(guān)聯(lián)的引用隊(duì)列中。

應(yīng)用場景:

  • 程序可以通過判斷引用隊(duì)列中是否存在該對象的虛引用,來了解這個對象是否將要被回收??梢?strong>用來作為GC回收Object的標(biāo)志。
  • 可以用虛引用來管理堆外內(nèi)存。

Reference和ReferenceQueue

四大引用的父類Reference和ReferenceQueue

在Reference中有5個非常重要的屬性:referent,next,discovered,pending,queue。

//5個非常重要的屬性
private T referent;         /* Treated specially by GC */
volatile ReferenceQueue<? super T> queue;
Reference next;
transient private Reference<T> discovered;  /* used by VM */
private static Reference<Object> pending = null;

可以把每個Reference看做一個節(jié)點(diǎn),多個Reference通過next,discovered,pending 進(jìn)行關(guān)聯(lián)

  • referent就是Reference實(shí)際引用的對象。
  • 通過next屬性,可以構(gòu)建ReferenceQueue。
  • 通過discovered屬性,可以構(gòu)建Discovered List。
  • 通過pending屬性,可以構(gòu)建Pending List。

四大狀態(tài)

上圖就是Reference 的四個狀態(tài)

  //Reference的兩個構(gòu)造方法,一個帶隊(duì)列,一個不帶
Reference(T referent) { 
        this(referent, null);
    }
?
    Reference(T referent, ReferenceQueue<? super T> queue) {
        this.referent = referent;
        this.queue = (queue == null) ? ReferenceQueue.NULL : queue;
    }
?

對于帶ReferenceQueue的Reference,GC會把要回收對象的Reference放到ReferenceQueue中,后續(xù)該Reference需要程序員自己處理 (調(diào)用poll方法) 。

不帶ReferenceQueue的Reference, 由GC自己處理,待回收的對象其Reference狀態(tài)會變成Inactive。

  • 創(chuàng)建好了Reference,就進(jìn)入active狀態(tài)。
  • active狀態(tài)下,如果引用對象的可到達(dá)狀態(tài)發(fā)送變化就會轉(zhuǎn)變成Inactive或Pending狀態(tài)。
  • Inactive狀態(tài)很好理解,到達(dá)Inactive狀態(tài)的Reference狀態(tài)不能被改變,會等待GC回收。
  • Pending狀態(tài)代表等待入Queue,Reference內(nèi)部有個ReferenceHandler,會調(diào)用enqueue方法,將Pending對象入到Queue中入Queue的對象,其狀態(tài)就變成了Enqueued。
  • Enqueued狀態(tài)的對象,如果調(diào)用poll方法從ReferenceQueue拿出,則該Reference的狀態(tài)就變成了Inactive,等待GC的回收。

這就是Reference的一個完整的生命周期。

三個Queue/List

三個Queue/List:ReferenceQueue,discovered List和pending List。

  • ReferenceQueue它本質(zhì)是由Reference中的next連接而成的。用來存儲GC待回收的對象。
  • pending List就是待入ReferenceQueue的list。
  • discovered List這個有點(diǎn)特別,在Pending狀態(tài)時候,discovered List就等于pending List。 在Active狀態(tài)的時候discovered List實(shí)際上維持的是一個引用鏈。通過這個引用鏈,我們可以獲得引用的鏈?zhǔn)浇Y(jié)構(gòu),當(dāng)某個Reference狀態(tài)不再是Active狀態(tài)時,需要將這個Reference從discovered List中刪除。

總結(jié)

Java的四種引用的級別由高到低依次為:強(qiáng)引用 > 軟引用 > 弱引用 > 虛引用

回收時機(jī)用途生存時間
強(qiáng)重來不會對象的一般狀態(tài)JVM停止運(yùn)行時終止
內(nèi)存不足 時聯(lián)合引用隊(duì)列構(gòu)造有效期短、占內(nèi)存大,生命周期長的對象的二級高速緩沖器(內(nèi)存不足的時候清空)內(nèi)存不足 時終止
在垃圾回收時聯(lián)合引用隊(duì)列構(gòu)造有效期短、占內(nèi)存大,生命周期長的對象的一級高速緩沖器(發(fā)生GC的時候清空)GC運(yùn)行后終止
在垃圾回收時聯(lián)合引用隊(duì)列來跟蹤對象被垃圾回收器回收的活動GC運(yùn)行后終止

以上就是詳解Java中的四種引用類型(強(qiáng)軟弱虛)的詳細(xì)內(nèi)容,更多關(guān)于Java引用類型的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • SpringBoot中EasyExcel實(shí)現(xiàn)execl導(dǎo)入導(dǎo)出

    SpringBoot中EasyExcel實(shí)現(xiàn)execl導(dǎo)入導(dǎo)出

    本文主要介紹了SpringBoot中EasyExcel實(shí)現(xiàn)execl導(dǎo)入導(dǎo)出,實(shí)現(xiàn)了如何準(zhǔn)備環(huán)境、創(chuàng)建實(shí)體類、自定義轉(zhuǎn)換器以及編寫導(dǎo)入邏輯的步驟和示例代碼,感興趣的可以了解下
    2023-06-06
  • springboot docker原理及項(xiàng)目構(gòu)建

    springboot docker原理及項(xiàng)目構(gòu)建

    這篇文章主要介紹了springboot docker原理及項(xiàng)目構(gòu)建,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2019-11-11
  • Spring cloud config 配置文件加密方式

    Spring cloud config 配置文件加密方式

    這篇文章給大家介紹了Spring cloud config 配置文件加密方式,非常不錯,具有一定的參考借鑒價值,感興趣的朋友跟隨腳步之家小編一起學(xué)習(xí)吧
    2018-05-05
  • java常用Lambda表達(dá)式使用場景源碼示例

    java常用Lambda表達(dá)式使用場景源碼示例

    這篇文章主要為大家介紹了java常用Lambda表達(dá)式使用場景源碼示例及應(yīng)用解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步
    2022-03-03
  • Spring注解配置實(shí)現(xiàn)過程詳解

    Spring注解配置實(shí)現(xiàn)過程詳解

    這篇文章主要介紹了Spring注解配置實(shí)現(xiàn)過程詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-08-08
  • Java排序算法三之歸并排序的遞歸與非遞歸的實(shí)現(xiàn)示例解析

    Java排序算法三之歸并排序的遞歸與非遞歸的實(shí)現(xiàn)示例解析

    這篇文章主要介紹了Java排序算法三之歸并排序的遞歸與非遞歸的實(shí)現(xiàn)示例解析,文章通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-08-08
  • Java定時器Timer的源碼分析

    Java定時器Timer的源碼分析

    通過源碼分析,我們可以更深入的了解其底層原理。本文將通過Timer的源碼,帶大家深入了解Java?Timer的使用,感興趣的小伙伴可以了解一下
    2022-11-11
  • Java Idea高效率配置技巧實(shí)例解析

    Java Idea高效率配置技巧實(shí)例解析

    這篇文章主要介紹了Java Idea高效率配置技巧實(shí)例解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-04-04
  • Spring學(xué)習(xí)筆記3之消息隊(duì)列(rabbitmq)發(fā)送郵件功能

    Spring學(xué)習(xí)筆記3之消息隊(duì)列(rabbitmq)發(fā)送郵件功能

    這篇文章主要介紹了Spring學(xué)習(xí)筆記3之消息隊(duì)列(rabbitmq)發(fā)送郵件功能的相關(guān)資料,非常不錯,具有參考借鑒價值,需要的朋友可以參考下
    2016-07-07
  • 聊聊Spring?Cloud?Gateway過濾器精確控制異常返回問題

    聊聊Spring?Cloud?Gateway過濾器精確控制異常返回問題

    這篇文章主要介紹了Spring?Cloud?Gateway過濾器精確控制異常返回問題,本篇任務(wù)就是分析上述現(xiàn)象的原因,通過閱讀源碼搞清楚返回碼和響應(yīng)body生成的具體邏輯,需要的朋友可以參考下
    2021-11-11

最新評論