Android性能提升之強(qiáng)引用、軟引用谦疾、弱引用南蹂、虛引用使用

轉(zhuǎn)載請把頭部出處鏈接和尾部二維碼一起轉(zhuǎn)載,本文出自逆流的魚yuiop:http://blog.csdn.net/hejjunlin/article/details/52637333
背景:收到公眾投稿念恍,《從面試題中看Java的Reference(引用)》六剥,分析的很不錯(cuò),總感覺少了實(shí)際的例子和應(yīng)用場景峰伙。于是結(jié)合自己工作中場景疗疟,小總結(jié)一下⊥ィ看下Agenda如下:

  • 強(qiáng)引用
  • 軟引用
  • 弱引用
  • 什么時(shí)候使用軟引用策彤,什么時(shí)候使用弱引用?
  • 虛引用

一顿膨、強(qiáng)引用

Java中的引用锅锨,類似于C++的指針。通過引用恋沃,可以對堆中的對象進(jìn)行操作必搞。在某個(gè)函數(shù)中,當(dāng)創(chuàng)建了一個(gè)對象囊咏,該對象被分配在堆中恕洲,通過這個(gè)對象的引用才能對這個(gè)對象進(jìn)行操作。

這里寫圖片描述

假設(shè)以上代碼是在方法內(nèi)運(yùn)行的梅割,那么局部變量str將被分配在椝冢空間上,而對象StringBuffer實(shí)例户辞,被分配在堆空間中泌类。局部變量str指向StringBuffer實(shí)例所在的堆空間,通過str可以操作該實(shí)例底燎,那么str就是StringBuffer的引用刃榨。

這里寫圖片描述

此時(shí),運(yùn)行一個(gè)賦值語句:

這里寫圖片描述

那么双仍,str所指向的對象也將被str1所指向枢希,同時(shí)在局部棧空間上會(huì)分配空間存放str1變量朱沃。此時(shí)苞轿,該StringBuffer實(shí)例就有兩個(gè)引用茅诱。對引用的”==”操作用于表示兩個(gè)操作數(shù)所指向的堆空間地址是否相同,不表示兩個(gè)操作數(shù)所指向的對象是否相等搬卒。

這里寫圖片描述

強(qiáng)引用特點(diǎn):

  • 強(qiáng)引用可以直接訪問目標(biāo)對象瑟俭。
  • 強(qiáng)引用所指向的對象在任何時(shí)候都不會(huì)被系統(tǒng)回收。JVM寧愿拋出OOM異常秀睛,也不會(huì)回收強(qiáng)引用所指向的對象尔当。
  • 強(qiáng)引用可能導(dǎo)致內(nèi)存泄露。

二蹂安、軟引用

軟引用是除了強(qiáng)引用外椭迎,最強(qiáng)的引用類型√镉可以通過java.lang.ref.SoftReference使用軟引用畜号。一個(gè)持有軟引用的對象,不會(huì)被JVM很快回收允瞧,JVM會(huì)根據(jù)當(dāng)前堆的使用情況來判斷何時(shí)回收简软。當(dāng)堆的使用率臨近閾值時(shí),才會(huì)回收軟引用的對象述暂。
看下我工作中使用到軟引用的場景痹升,加載一個(gè)1080x1920分辨率的圖,約900多K, 對于我們來說畦韭,這個(gè)圖已是非常大了疼蛾。

這里寫圖片描述
  • 首先通過BitmapFactory.decodeStream構(gòu)造一個(gè)大圖bitmap

  • 然后把這個(gè)bitmap轉(zhuǎn)成Drawble類型,構(gòu)成強(qiáng)引用艺配。

  • 接著使用SoftReference構(gòu)造這個(gè)drawable對象的軟引用drawables.

  • 最后通過軟引用的get()方法察郁,取得drawable對象實(shí)例的強(qiáng)引用,發(fā)現(xiàn)對象被未回收转唉。在GC在內(nèi)存充足的情況下皮钠,不會(huì)回收軟引用對象。

  • 在實(shí)際中赠法,一起請求很多相關(guān)圖片麦轰,從網(wǎng)絡(luò),這時(shí)就會(huì)請求非常多的內(nèi)存空間砖织,導(dǎo)致內(nèi)存吃緊原朝,系統(tǒng)開始會(huì)GC。這次GC后镶苞,drawables.get()不再返回Drawable對象,而是返回null鞠评,這時(shí)屏幕上背景圖不顯示茂蚓,說明在系統(tǒng)內(nèi)存緊張的情況下,軟引用被回收。

  • 使用軟引用以后聋涨,在OutOfMemory異常發(fā)生之前晾浴,這些緩存的圖片資源的內(nèi)存空間可以被釋放掉的,從而避免內(nèi)存達(dá)到上限牍白,避免Crash發(fā)生脊凰。

  • 需要注意的是,在垃圾回收器對這個(gè)Java對象回收前茂腥,SoftReference類所提供的get方法會(huì)返回Java對象的強(qiáng)引用狸涌,一旦垃圾線程回收該Java對象之后,get方法將返回null最岗。所以在獲取軟引用對象的代碼中帕胆,一定要判斷是否為null,以免出現(xiàn)NullPointerException異常導(dǎo)致應(yīng)用崩潰般渡。

到底什么時(shí)候使用軟引用懒豹,什么時(shí)候使用弱引用呢笼沥?

個(gè)人認(rèn)為屈雄,如果只是想避免OutOfMemory異常的發(fā)生捐康,則可以使用軟引用比原。如果對于應(yīng)用的性能更在意钥弯,想盡快回收一些占用內(nèi)存比較大的對象祭刚,則可以使用弱引用译隘。

還有就是可以根據(jù)對象是否經(jīng)常使用來判斷坏匪。如果該對象可能會(huì)經(jīng)常使用的淘这,就盡量用軟引用剥扣。如果該對象不被使用的可能性更大些,就可以用弱引用铝穷。

另外钠怯,和弱引用功能類似的是WeakHashMap。WeakHashMap對于一個(gè)給定的key曙聂,其映射的存在并不阻止垃圾回收器對該鍵的回收晦炊,回收以后,其條目從映射中有效地移除宁脊。WeakHashMap使用ReferenceQueue實(shí)現(xiàn)的這種機(jī)制断国。

三、 弱引用

弱引用是一種比軟引用較弱的引用類型榆苞。在系統(tǒng)GC時(shí)稳衬,只要發(fā)現(xiàn)弱引用,不管系統(tǒng)堆空間是否足夠坐漏,都會(huì)將對象進(jìn)行回收薄疚。但是碧信,由于垃圾回收器的線程通常優(yōu)先級很低,因此街夭,并一不定能很快的發(fā)現(xiàn)持有弱引用的對象砰碴。這種情況下,弱引用對象可以存在較長的一段時(shí)間板丽。一旦一個(gè)弱引用對象被垃圾回收器回收呈枉,便會(huì)加入到一個(gè)注冊引用隊(duì)列中。
看一個(gè)工作中實(shí)例:播放器的播放Panel埃碱,是一個(gè)View猖辫,就是在視頻播放時(shí),可以show乃正、hide, 也可以拖拽進(jìn)度條之類住册,還有上面的音量,亮度調(diào)節(jié)等瓮具。這樣一個(gè)view荧飞,我們用弱引用,因?yàn)樵谝曨l播放過程中名党,不論硬解還是軟解叹阔,都將占用大量內(nèi)存。保證視頻的渲染效果传睹。
在VideoControllerView.java 有如下一段代碼:

這里寫圖片描述

在GC之前耳幢,弱引用對象并未被垃圾回收器發(fā)現(xiàn),因此通過mView.get()方法可以取得對應(yīng)的強(qiáng)引用欧啤。但是只要進(jìn)行垃圾回收睛藻,弱引用對象一旦被發(fā)現(xiàn),便會(huì)立即被回收邢隧,并加入注冊引用隊(duì)列中店印。此時(shí),再次通過mView.get()方法取得強(qiáng)引用就會(huì)失敗倒慧。

注意:軟引用按摘,弱引用都非常適合來保存那些可有可無的緩存數(shù)據(jù)。如果這樣做纫谅,當(dāng)系統(tǒng)內(nèi)存不足時(shí)炫贤,這些緩存數(shù)據(jù)會(huì)被回收,不會(huì)導(dǎo)致內(nèi)存溢出付秕。而當(dāng)內(nèi)存資源充足時(shí)兰珍,這些緩存數(shù)據(jù)又可以存在相當(dāng)長的時(shí)間。

四询吴、 虛引用

  • 虛引用是所有引用類型中最弱的一個(gè)俩垃。一個(gè)持有虛引用的對象励幼,和沒有引用幾乎是一樣的,隨時(shí)都可能被垃圾回收器回收口柳。當(dāng)試圖通過虛引用的get()方法取得強(qiáng)引用時(shí),總是會(huì)失敗有滑。并且跃闹,虛引用必須和引用隊(duì)列一起使用,它的作用在于跟蹤垃圾回收過程毛好。
  • 當(dāng)垃圾回收器準(zhǔn)備回收一個(gè)對象時(shí)望艺,如果發(fā)現(xiàn)它還有虛引用,就會(huì)在垃圾回收后肌访,銷毀這個(gè)對象找默,獎(jiǎng)這個(gè)虛引用加入引用隊(duì)列。
  • 實(shí)際中幾乎沒用吼驶,暫不介紹惩激。

最后一張圖總結(jié)下:

這里寫圖片描述
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市蟹演,隨后出現(xiàn)的幾起案子风钻,更是在濱河造成了極大的恐慌,老刑警劉巖酒请,帶你破解...
    沈念sama閱讀 217,657評論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件骡技,死亡現(xiàn)場離奇詭異,居然都是意外死亡羞反,警方通過查閱死者的電腦和手機(jī)布朦,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,889評論 3 394
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來昼窗,“玉大人是趴,你說我怎么就攤上這事「囡” “怎么了右遭?”我有些...
    開封第一講書人閱讀 164,057評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長缤削。 經(jīng)常有香客問我窘哈,道長,這世上最難降的妖魔是什么亭敢? 我笑而不...
    開封第一講書人閱讀 58,509評論 1 293
  • 正文 為了忘掉前任滚婉,我火速辦了婚禮,結(jié)果婚禮上帅刀,老公的妹妹穿的比我還像新娘让腹。我一直安慰自己远剩,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,562評論 6 392
  • 文/花漫 我一把揭開白布骇窍。 她就那樣靜靜地躺著瓜晤,像睡著了一般。 火紅的嫁衣襯著肌膚如雪腹纳。 梳的紋絲不亂的頭發(fā)上痢掠,一...
    開封第一講書人閱讀 51,443評論 1 302
  • 那天,我揣著相機(jī)與錄音嘲恍,去河邊找鬼足画。 笑死,一個(gè)胖子當(dāng)著我的面吹牛佃牛,可吹牛的內(nèi)容都是我干的淹辞。 我是一名探鬼主播,決...
    沈念sama閱讀 40,251評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼俘侠,長吁一口氣:“原來是場噩夢啊……” “哼象缀!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起兼贡,我...
    開封第一講書人閱讀 39,129評論 0 276
  • 序言:老撾萬榮一對情侶失蹤攻冷,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后遍希,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體等曼,經(jīng)...
    沈念sama閱讀 45,561評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,779評論 3 335
  • 正文 我和宋清朗相戀三年凿蒜,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了禁谦。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,902評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡废封,死狀恐怖州泊,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情漂洋,我是刑警寧澤遥皂,帶...
    沈念sama閱讀 35,621評論 5 345
  • 正文 年R本政府宣布,位于F島的核電站刽漂,受9級特大地震影響演训,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜贝咙,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,220評論 3 328
  • 文/蒙蒙 一样悟、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦窟她、人聲如沸陈症。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,838評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽录肯。三九已至,卻和暖如春吊说,著一層夾襖步出監(jiān)牢的瞬間嘁信,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,971評論 1 269
  • 我被黑心中介騙來泰國打工疏叨, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人穿剖。 一個(gè)月前我還...
    沈念sama閱讀 48,025評論 2 370
  • 正文 我出身青樓蚤蔓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親糊余。 傳聞我的和親對象是個(gè)殘疾皇子秀又,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,843評論 2 354

推薦閱讀更多精彩內(nèi)容