java中的軟引用和弱引用
在java 中除了基本資料型別之外,其他都是引用資料型別,而引用資料型別又分類四種
強引用
指向通過new得到的記憶體空間的引用叫做強引用,比如 String a = new String(“123”),其中的a就是一個強引用,它指向了一塊記憶體為123的堆空間。平時我們用的最多的也是強型別.
軟引用
軟引用(在java 中可以用SoftReference類實現)的含義是,如果一個 物件 具有軟引用,如果虛擬機器記憶體不足或發生oom之前,JVM虛擬機器會回收這些被軟引用指向的記憶體區域,如果記憶體足夠,便不會回收。一般用於存放較為敏感的資訊。
弱引用
弱引用和軟引用較為相識(通過WeakReference類實現),他們的區別在於,垃圾回收器一旦發現某塊記憶體上有且僅有弱引用(一定要注意只有弱引用,沒有強引用)指向這塊記憶體的地址空間,不管當前記憶體是否足夠,這這塊被弱引用指向的記憶體空間都會GC回收。
虛引用
虛引用也叫幻象引用,通過PhantomReference類來實現,無法通過虛引用訪問物件的任何屬性和函式,虛引用只是提供了了一種確保物件在finalize以後可以做某些事情的機制。(目前學習階段沒接觸到如何使用它,以後碰到了再補充一篇)
下面我們看看這軟引用和弱引用之間的區別
import java.lang.ref.SoftReference;
import java.lang.ref.WeakReference;
/**
* 引用區別
*
* @author koala
* @date 2018/5/26
*/
public class ReferenceDemo {
public static void main(String[] args) {
/**
* str 指向堆記憶體內容為abc的地址
*/
String str = new String("abc");
// 軟引用
SoftReference<String> softReference = new SoftReference<String>(str);
str = null;
System.gc();
System.out.println(softReference.get()); // 執行結果: abc
String abc = new String("123");
// 弱引用
WeakReference<String> weekReference = new WeakReference<String>(abc);
// 去掉強引用
abc = null;
System.gc();
System.out.println(weekReference.get()); // 執行結果: null
}
}
,一般軟軟引用可以做一些快取處理,如果不使用第三方快取機制,可以使用軟引用實現快取方案,比如,文章快取(從軟引用裡面去取文章內容,如果沒有再從資料庫中取,在刷回到軟引用中)
我們來使用WeakHashMap來了解弱引用的使用場景
“`
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.WeakHashMap;
/**
* 弱引用物件
*
* @author koala
* @date 2018/5/26
*/
public class WeekHashMapDemo {
public static void main(String[] args) {
/**
* // 假設堆空間為1000 A
*
* a -> A
*
*/
String a = new String("ABC");
/**
* // 假設堆空間為2000 B
*
* b -> B
*
*/
String b = new String("123");
Map weakMap = new WeakHashMap();
Map map = new HashMap(10);
/**
* a - > A -- 強引用
* map:(AAA) - > A -- 強引用
*
* b - > B -- 強引用
* map: (BBB) - > B -- 強引用
*/
map.put(a,"AAA");
map.put(b,"BBB");
/**
* a - > A -- 強引用
* map:(AAA) - > A -- 強引用
* weakmap:(aaa) -> A -- 弱引用
*
* b - > B -- 強引用
* map: (BBB) - > B -- 強引用
* weakmap:(bbb) -> B -- 弱引用
*/
weakMap.put(a,"aaa");
weakMap.put(b,"bbb");
/**
* a - > A -- 強引用
* weakmap:aaa -> A -- 弱引用
*
* b - > B -- 強引用
* map: BBB - > B -- 強引用
* weakmap:bbb -> B -- 弱引用
*/
map.remove(a);
/**
* weakmap:aaa -> A -- 弱引用
*
* map: BBB - > B -- 強引用
* weakmap:bbb -> B -- 弱引用
*/
a = null;
b = null;
System.gc();
/**
* 輸出結果
* map,123:BBB
*
* 分析, 在gc之前,map集合a引用已經被移除,只有一個b引用是一個強型別
*/
System.out.println(a);
Iterator i = map.entrySet().iterator();
while (i.hasNext()){
Map.Entry en = (Map.Entry) i.next();
System.out.println("map,"+en.getKey()+":"+en.getValue());
}
/**
* 輸出結果
* weakmap,123:bbb
*
* 分析:weakmap集合key值為a的引用(指向地址A)是一個弱引用,gc會回收被弱引用所引用的物件,所以A地址空間會被回收(A地址中只有被弱引用引用)
* weakmap集合key值為b的引用,由於在map集合中有強引用指向地址B,及時weakmap中key值為b弱引用,指向這個地址空間,此地址空間也不會被回收
*
*/
Iterator j = weakMap.entrySet().iterator();
while (j.hasNext()){
Map.Entry en = (Map.Entry) j.next();
System.out.println("weakmap,"+en.getKey()+":"+en.getValue());
}
}
}
無論是軟引用還是弱引用獲取虛引用都可以使用引用佇列ReferenceQueue配合使用,可以通過程式判斷是否加入了某些引用,那些引用被回收了,從而我們可以在引用回收之前採取一些程式行動