1. 程式人生 > >java中的軟引用和弱引用

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配合使用,可以通過程式判斷是否加入了某些引用,那些引用被回收了,從而我們可以在引用回收之前採取一些程式行動