Java中的引用概念的理解與實踐


最初看到了這篇文章十分鐘理解Java中的弱引用讓我有想法嘗試去理解java.lang.ref.WeakReference類的弱引用垦搬。首先抱歉對該篇文章會有過多引用的地方呼寸。

一。什么是引用

實際上猴贰,Java中存在四種引用对雪,它們由強到弱依次是:強引用、軟引用米绕、弱引用瑟捣、虛引用。下面我們簡單介紹下除弱引用外的其他三種引用:

強引用(Strong Reference):通常我們通過new來創(chuàng)建一個新對象時返回的引用就是一個強引用栅干,若一個對象通過一系列強引用可到達迈套,它就是強可達的(strongly reachable),那么它就不被回收

軟引用(Soft Reference):軟引用和弱引用的區(qū)別在于碱鳞,若一個對象是弱引用可達桑李,無論當前內存是否充足它都會被回收,而軟引用可達的對象在內存不充足時才會被回收窿给,因此軟引用要比弱引用“強”一些

虛引用(Phantom Reference):虛引用是Java中最弱的引用贵白,那么它弱到什么程度呢?它是如此脆弱以至于我們通過虛引用甚至無法獲取到被引用的對象崩泡,虛引用存在的唯一作用就是當它指向的對象被回收后禁荒,虛引用本身會被加入到引用隊列中,用作記錄它指向的對象已被銷毀角撞。

弱引用:

弱引用對象的存在不會阻止它所指向的對象變被垃圾回收器回收呛伴。弱引用最常見的用途是實現規(guī)范映射(canonicalizing mappings,比如哈希表)谒所。假設垃圾收集器在某個時間點決定一個對象是弱可達的(weakly reachable)(也就是說當前指向它的全都是弱引用)热康,這時垃圾收集器會清除所有指向該對象的弱引用,然后垃圾收集器會把這個弱可達對象標記為可終結(finalizable)的百炬,這樣它們隨后就會被回收褐隆。與此同時或稍后,垃圾收集器會把那些剛清除的弱引用放入創(chuàng)建弱引用對象時所登記到的引用隊列(Reference Queue)中剖踊。

引用隊列:

WeakReference類有兩個構造函數:

WeakReference(T referent)//創(chuàng)建一個指向給定對象的弱引用

WeakReference(T referent, ReferenceQueue q)//創(chuàng)建一個指向給定對象并且登記到給定引用隊列的弱引用

我們可以看到第二個構造方法中提供了一個ReferenceQueue類型的參數庶弃,通過提供這個參數,我們便把創(chuàng)建的弱引用對象注冊到了一個引用隊列上德澈,這樣當它被垃圾回收器清除時歇攻,就會把它送入這個引用隊列中,我們便可以對這些被清除的弱引用對象進行統(tǒng)一管理梆造。

二缴守。使用弱引用

首先我把文章作者提出的場景拿過來用:

現在有一個Product類代表一種產品葬毫,這個類被設計為不可擴展的,而此時我們想要為每個產品增加一個編號屡穗。一種解決方案是使用HashMap<Product,Integer>,于是問題來了贴捡,如果我們已經不再需要一個Product對象存在于內存中(比如已經賣出了這件產品),假設指向它的引用為productA村砂,我們這時會給productA賦值為null烂斋,然而這時productA過去指向的Product對象并不會被回收,因為它顯然還被HashMap引用著础废。所以這種情況下汛骂,我們想要真正的回收一個Product對象,僅僅把它的強引用賦值為null是不夠的评腺,還要把相應的條目從HashMap中移除帘瞭。顯然“從HashMap中移除不再需要的條目”這個工作我們不想自己完成,我們希望告訴垃圾收集器:“在只有HashMap中的key在引用著Product對象的情況下蒿讥,就可以回收相應Product對象了蝶念。”

那該如何解決上述問題诈悍?我們就會考慮用弱引用概念來解決上述問題祸轮,我們會把hashmap的key由product換為WeakReference<Product>:

本來:

Hashmap<Product ,Integer> hashmap = new Hashmap<>();

Product productA ;

for(int i=0;i<10;i++){

?Product product = new Product();//這句話表明product指向Product對象

if(i=0) productA = product;

hashmap.put(product,i);

}

當把productA = null時兽埃,并不能把hashmap對應的product回收侥钳。

當改為:

Hashmap hashmap = new Hashmap<>();

WeakReference<Product> weakProductA ;

for(int i=0;i<10;i++){

Product product = new Product();

WeakReference<Product> weakProduct =new WeakReference<>(product);

if(i=0) weakProductA= weakProduct;

hashmap.put(product,i);

}

現在,弱引用對象weakProductA就指向了Product對象productA柄错。那么我們怎么通過weakProduct獲取它所指向的Product對象productA呢舷夺?很簡單,只需要下面這句代碼:

Product product = weakProductA.get()售貌;

當我們把product=null時给猾,表明它所引用的Product已經無需存在于內存中,這時指向這個Product對象的就是由弱引用對象weakProductA了颂跨,那么顯然這時候相應的Product對象時弱可達的敢伸,所以指向它的弱引用會被清除,這個Product對象隨即會被回收恒削,指向它的弱引用對象會進入引用隊列中池颈。

其實對于上述問題,java本身提供了WeakHashMap類钓丰,使用和這個類躯砰,它的鍵自然就是弱引用對象,無需我們再手動包裝原始對象携丁。

三琢歇。使用弱引用

只要某個對象有強引用與之關聯(lián),JVM必定不會回收這個對象,即使在內存不足的情況下李茫,JVM寧愿拋出OutOfMemory錯誤也不會回收這種對象揭保。所以回歸到android本身,最容易引起android系統(tǒng)OOM的最大問題就是bitmap問題魄宏,因為bitmap本身所占內存就很大掖举,處理不得當,系統(tǒng)就會OOM娜庇,發(fā)生崩潰塔次。為了保證系統(tǒng)不因bitmap發(fā)生OOM,我們考慮用軟引用:

Java中的SoftReference即對象的軟引用名秀。如果一個對象具有軟引用励负,內存空間足夠,垃圾回收器就不會回收它匕得;如果內存空間不足了继榆,就會回收這些對象的內存。只要垃圾回收器沒有回收它汁掠,該對象就可以被程序使用略吨。軟引用可用來實現內存敏感的高速緩存。使用軟引用能防止內存泄露考阱,增強程序的健壯性翠忠。

下面有一個這樣的應用場景:我們通過圖片本地路徑,可以索引到我們之前通過正常手段獲取對應的bitmap乞榨。

本來:

Hashmap<String,Bitmap> hashmap = new Hashmap<>();

public Bitmap getBmByPath(String path){

???? Bitmap bitmap = hashmap.get(path)

? ? ? if(bitmap!=null){

? ? ? ? ? ? return bitmap;

????? }else{

? ? ? ????? bitmap= getBitmapFromPath(path);

??????????? hashmap.put(path,bitmap);

??????????? return bitmap;

???? }

}

這樣設計導致系統(tǒng)內存不足時秽之,也不會主動回收存儲的bitmap。

所以改進為:

Hashmap<String,SoftReference<Bitmap>> hashmap = new Hashmap<>();

public Bitmap getBmByPath(String path){

???? SoftReference<Bitmap> softbitmap = hashmap.get(path)

???? if(softbitmap.get()!=null){

?????? return softbitmap.get();

??? }else{

????? bitmap= getBitmapFromPath(path);

????? SoftReference<Bitmap> d =new SoftReference<>(bitmap);

????? hashmap.put(path,d);

????? return bitmap;

??? }

}

總結:文章上面我寫了兩個引用吃既,一個是弱引用考榨,一個軟應用,為什么不同應用場景我選擇不同的引用鹦倚。我給大家分析一下河质,在我需要主動回收某對象時,希望它引用的那些對象也會被回收震叙,那我會選擇用軟引用掀鹅。當我需要在系統(tǒng)內存不足時,希望系統(tǒng)主動回收某對象時捐友,我會用弱引用淫半。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市匣砖,隨后出現的幾起案子科吭,更是在濱河造成了極大的恐慌昏滴,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,968評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件对人,死亡現場離奇詭異谣殊,居然都是意外死亡,警方通過查閱死者的電腦和手機牺弄,發(fā)現死者居然都...
    沈念sama閱讀 88,601評論 2 382
  • 文/潘曉璐 我一進店門姻几,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人势告,你說我怎么就攤上這事蛇捌。” “怎么了咱台?”我有些...
    開封第一講書人閱讀 153,220評論 0 344
  • 文/不壞的土叔 我叫張陵络拌,是天一觀的道長。 經常有香客問我回溺,道長春贸,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,416評論 1 279
  • 正文 為了忘掉前任遗遵,我火速辦了婚禮萍恕,結果婚禮上,老公的妹妹穿的比我還像新娘车要。我一直安慰自己允粤,他們只是感情好,可當我...
    茶點故事閱讀 64,425評論 5 374
  • 文/花漫 我一把揭開白布屯蹦。 她就那樣靜靜地躺著维哈,像睡著了一般绳姨。 火紅的嫁衣襯著肌膚如雪登澜。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,144評論 1 285
  • 那天飘庄,我揣著相機與錄音脑蠕,去河邊找鬼。 笑死跪削,一個胖子當著我的面吹牛谴仙,可吹牛的內容都是我干的。 我是一名探鬼主播碾盐,決...
    沈念sama閱讀 38,432評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼晃跺,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了毫玖?” 一聲冷哼從身側響起掀虎,我...
    開封第一講書人閱讀 37,088評論 0 261
  • 序言:老撾萬榮一對情侶失蹤凌盯,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后烹玉,有當地人在樹林里發(fā)現了一具尸體驰怎,經...
    沈念sama閱讀 43,586評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,028評論 2 325
  • 正文 我和宋清朗相戀三年二打,在試婚紗的時候發(fā)現自己被綠了县忌。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,137評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡继效,死狀恐怖症杏,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情瑞信,我是刑警寧澤鸳慈,帶...
    沈念sama閱讀 33,783評論 4 324
  • 正文 年R本政府宣布,位于F島的核電站喧伞,受9級特大地震影響走芋,放射性物質發(fā)生泄漏。R本人自食惡果不足惜潘鲫,卻給世界環(huán)境...
    茶點故事閱讀 39,343評論 3 307
  • 文/蒙蒙 一翁逞、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧溉仑,春花似錦挖函、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,333評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至振定,卻和暖如春必怜,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背后频。 一陣腳步聲響...
    開封第一講書人閱讀 31,559評論 1 262
  • 我被黑心中介騙來泰國打工梳庆, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人卑惜。 一個月前我還...
    沈念sama閱讀 45,595評論 2 355
  • 正文 我出身青樓膏执,卻偏偏與公主長得像,于是被迫代替她去往敵國和親露久。 傳聞我的和親對象是個殘疾皇子更米,可洞房花燭夜當晚...
    茶點故事閱讀 42,901評論 2 345

推薦閱讀更多精彩內容