天天看點

WeakReference and WeakHashMap

弱引用通過WeakReference類實作,弱引用和軟引用很像,但弱引用的引用級别更低。對于隻有弱引用的對象而言,當系統垃圾回收機制運作時,不管系統北村是否足夠,總會回收該對象所占用的記憶體。當然,并不是說當一個對象隻有弱引用時,它就會立即被回收-正如那些失去引用的對象一樣,必須等到系統垃圾回收機制運作時才會被回收。

import java.lang.ref.SoftReference;

import java.lang.ref.WeakReference;

public class WeakReferenceTest {

    public static void main(String[] args){

      Stringstr = newString("Java");

      Stringstr1 = newString("Java");

      SoftReference<String>sr = newSoftReference<String>(str1);

      WeakReference<String>wr = newWeakReference<String>(str);

      str= null;

      str1= null;

      System.out.println(sr.get());

      System.out.println(wr.get());

      System.gc();

      System.runFinalization();

      System.out.println(sr.get());

      System.out.println(wr.get());

    }

}

Output:

Java

Java

Java

null

不要使用String str = “Java”;這樣就看不到運作效果,因為采用這樣定義的字元串系統會緩存這個字元串直接量(會使用強引用來引用它),系統不會回收被緩存的字元串常量。

弱引用具有很大的不确定性,因為每次垃圾回收機制執行時都會回收弱引用的對象,而垃圾回收機制的運作又不受程式員的控制,是以程式擷取弱引用所引用的Java對象時必須小心空指針異常-通過弱引用所擷取的Java對象可能是null.

由于垃圾回收的不确定性,當程式希望從弱引用中取出被引用對象時,可能這個被引用對象已經被釋放了。如果程式需要使用那個被引用的對象,則必須重新建立新對象。

public class WeakReferenceTest {

    public static void main(String[] args){

      Stringstr = newString("Java");

      Stringstr1 = newString("Java");

      SoftReference<String>sr = newSoftReference<String>(str1);

      WeakReference<String>wr = newWeakReference<String>(str);

      str= null;

      str1= null;

      System.out.println(sr.get());

      System.out.println(wr.get());

      System.gc();

      System.runFinalization();

      if(wr.get() == null){

            str= new String("Java");

            wr= newWeakReference<String>(str);

            System.out.println(wr.get());

      }

      System.out.println(sr.get());

      System.out.println(wr.get());

    }

}

Output:

Java

Java

Java

Java

Java

與weakReference功能類似的還有WeakHashMap,當程式有大量的java對象需要使用弱引用來引用時,可以考慮使用weakHashMap來儲存它們。

import java.util.WeakHashMap;

class CrazyKey{

      String name;

      public CrazyKey(String name){

            this.name =name;

      }

      public inthashCode(){

            return name.hashCode();

      }

      public boolean equals(Object obj){

            if(obj==this){

                  returntrue;

            }

            if(obj!=null && obj.getClass() == CrazyKey.class){

                  returnname.equals(((CrazyKey)obj).name);

            }

            returnfalse;

      }

      public String toString(){

            return "CrazyKey[name=" + name +"]";

      }

}

public class WeakHashMapTest {

    public static void main(String[] args)throws InterruptedException{

      WeakHashMap<CrazyKey,String>map = newWeakHashMap<CrazyKey,String>();

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

            map.put(new CrazyKey(i+1+""),"value"+(i+11));

      }

      System.out.println(map);

      System.out.println(map.get(new CrazyKey("2")));

      System.gc();

      Thread.sleep(50);

      System.out.println(map);

      System.out.println(map.get(new CrazyKey("2")));

    }

}

Output:

{CrazyKey[name=8]=value18,CrazyKey[name=9]=value19, CrazyKey[name=4]=value14, CrazyKey[name=5]=value15,CrazyKey[name=6]=value16, CrazyKey[name=7]=value17, CrazyKey[name=10]=value20,CrazyKey[name=1]=value11, CrazyKey[name=2]=value12, CrazyKey[name=3]=value13}

value12

{}

null

在垃圾回收機制運作之前,WeakHashMap的功能與普通HashMap并沒有太大的差別,它們的功能相似。但一旦垃圾回收機制被執行,WeakHashMap中所有key-value就都會被清空,除非某些Key還有強引用在引用它們。