這篇文章咱們來聊聊軟引用和弱引用對內存性能的幫助,你們在平時的開發過程當中,對於內存性能作過哪些調優工做,其中的一個方法就是咱們可使用軟引用和弱引用。
java
軟引用(SoftReference):數據庫
若是一個對象只具備軟引用,而當前虛擬機堆內存空間足夠時,那麼垃圾回收器就不會回收它,反之就會回收當前軟引用指向的對象。緩存
弱引用(WeakReference):ide
垃圾回收器發現一個對象上只有弱引用,此時無論內存夠不夠,這個對象都會被回收。性能
下面經過一段簡單的代碼來看一下軟引用和弱引用的具體用法;網站
import java.lang.ref.SoftReference;import java.lang.ref.WeakReference;
public class ReferenceDemo { public static void main(String[] args) { //強引用 String str = new String("abc"); //弱引用 SoftReference<String> softRef = new SoftReference<>(str); str = null; //去掉強引用 System.gc(); //垃圾回收器進行回收 System.out.println(softRef.get());
//強引用 String abc = new String("123"); //弱引用 WeakReference<String> weakRef = new WeakReference<>(abc); abc = null; //去掉強引用 System.gc(); //垃圾回收器進行垃圾回收 System.out.println(weakRef.get()); }}
經過上面這個例子,咱們來分析一下軟引用和弱引用的差異,首先看弱引用的例子,咱們先定義了一個強引用對象,而後咱們給這個強引用對象加了一個軟引用,這裏要注意軟引用的寫法是SoftReference
,而後咱們經過str = null來去掉str對象的強引用,此時str這個對象只有一個軟引用,經過System.gc()
;咱們進行了一次垃圾回收,由於str這個對象只有一個弱引用,沒有強引用,而這是內存足夠,因此說這個對象是不會被垃圾回收器回收的,它的輸出是abc。spa
而後咱們看第二個例子,首先定義了一個強引用對象,而後給這個對象加了一個弱引用,這裏給對象加弱引用的方法是WeakReference
,咱們再經過abc = null,去掉這個對象的強引用,此時abc這個對象就只有一個弱引用,經過System.gc()
進行了一次垃圾回收,這個適合abc這個對象沒有強引用,只有一個弱引用,根據弱引用的定義,在垃圾回收以後,這個對象會被回收的,因此說弱引用的輸出結果是null。code
那麼最終的結果是很多咱們分析的這樣,咱們run一下看看,以下圖所示,只有弱引用的對象在內存空間足夠的時候沒有被回收,對象在只有弱引用的時候被垃圾回收器回收。orm
好比說在一個博客管理系統裏,爲了提高訪問性能,用戶在點擊博文時,若是這篇博文有緩存,這樣其餘用戶在點擊這篇博文時,就直接從內存中加載,而不走數據庫,而這樣能夠下降響應時間,首先,咱們定義一個Content類,來封裝博文的內容。對象
而後咱們定義一個類型爲HashMap<String,SoftReerence<Content>>
對象來保存緩存內容,其中鍵是String類型表示文章id,值是一個指向Content的軟鏈接,隨後當用戶點擊某個id時,用id去HashMap中找,若是找到,而且Content的內容不爲空,那麼從中拿數據並直接作展現動做,這樣的話,不要查詢數據庫,能夠提升性能。在其中用id找不到,或者雖然找到,可是其中內容爲空,那麼咱們就從數據庫裏面去找,找到文章後同時把它插入到HashMap這個緩存中,這個地方要注意,插入緩存後要刪除Content上的強引用,從而保證只有一個軟引用。
這樣用軟引用的好處,假設咱們用1GB的內存,緩存了10000篇博文,那麼這10000篇博文,在內存空間上只有軟引用,沒有強引用,若是內存空間足夠時,那麼咱們能夠經過緩存來提高性能,可是萬一內存不夠,咱們能夠依次釋放這10000篇博文佔用的內存,而釋放時不會影響業務流程,最多就是稍微影響性能。
對比一下,若是這裏咱們用強引用來作緩存,會有什麼後果,因爲咱們不知道何時該撤銷在Content上的強引用,因此說找不到一個合適的機會來釋放緩存。若是咱們再引入一套緩存機制,這就屬於額外工做了,就沒有像軟引用這樣直接了。
在某個電商網站中,咱們會用Coupon類來保存優惠券信息,好比咱們其中能夠定義優惠券打折程度,有效期和做用範圍等等,當咱們從數據庫中,獲得全部的優惠券信息以後,會用一個List<Coupon>類型來保存優惠券,這個時候,若是咱們想保存優惠券和它關聯的用戶時,咱們能夠用WeakHashMap<Coupon,List<WeakReference<USer>>>
這樣類型的weakCouponHM對
象,這樣的對象,它主體是WeakHashMap
,也就是基於弱引用的HashMap,其中鍵是Coupon
類型,值是指向List<WeakReference<User>>
的弱引用,想象一下,若是有一百個優惠券,那麼它會存儲在List<Coupon>
類型中的couponList
中,同時在WeakHashMap
這個類型對象裏,也會用鍵的形式存儲這100個優惠券。加入有10000個用戶,咱們能夠用List<User>
類型的userList
對象來保存它們。
咱們假設coupon1這個優惠券對應100個用戶,那麼咱們能夠經過weakCouponHM.put()
方法來添加它們的對於關係,其中是以弱引用的方法, 保存了coupon1所對應的100個用戶,同理,當假設某個優惠券3,用弱引用的方式指向這100個用戶,當某個用戶註銷帳戶時,它會從List<User>
這個對象中刪除,換句話說,這個對象就只有在weakCouponHM
裏面的值,也就是隻有一個弱引用,在下次垃圾回收的時候回被清除,這樣coupon3上關聯的用戶它會被自動更新成99個。
相比之下,咱們不用弱引用而選擇用強引用,那麼咱們就在用戶被刪除以後,須要手動刪除用戶和優惠券之間的對應關係,若是忘了刪除就會出現代碼問題,相比之下,當咱們引用弱引用時,就會給咱們帶來「自動更新」這樣的好處。