WeakHashMap理解

来源:互联网 发布:mac cs6破解方法 编辑:程序博客网 时间:2024/04/30 21:57

WeakHashMap实现了Map接口,是HashMap的一种实现,他使用弱引用作为内部数据的存储方案,WeakHashMap可以作为简单缓存表的解决方案,当系统内存不够的时候,垃圾收集器会自动的清除没有在其他任何地方被引用的键值对。

  如果需要用一张很大的HashMap作为缓存表,那么可以考虑使用WeakHashMap,当键值不存在的时候添加到表中,存在即取出其值。

+ View Code?
1
2
3
4
5
WeakHashMap weakMap =new WeakHashMap<Integer,byte[]>();
for(inti = 0; i <10000; i++){
Integer ii =new Integer(i);
weakMap.put(ii,new byte[i]);
}

  

+ View Code?
1
2
3
4
5
HashMap map =new HashMap<Integer,byte[]>();
for(int i = 0; i < 10000; i++) {
  Integer ii =new Integer(i);
  map.put(ii,new byte[i]);
}

  这2段代码分别用-Xmx5M的参数运行,运行的结果是第一段代码可以很好的运行,第二段代码会出现“Java Heap Space”的错误,这说明用WeakHashMap存储,在系统内存不够用的时候会自动回收内存。

  如果WeakHashMap的key在系统内持有强引用,那么WeakHashMap就退化为HashMap,所有的表项无法被垃圾收集器自动清理。

 1    package com.froest.excel;

 2


 3   import java.util.Iterator;

 4  import java.util.Map;

 5  import java.util.WeakHashMap;

 6


 7  publicclass Test5 {

 8

 9   /**
10 * @param args

11   */


12         public staticvoid main(String[] args) {

13                             // TODO Auto-generated method stub
14                             WeakHashMap<AA, People1> weakMap1 =new WeakHashMap<AA, People1>();

15                             String b =new String("louhang1");

16                             AA a =new AA(b);

17                             BB bb =new BB(a);

18                             People1 p1 =new People1(bb);

19                             weakMap1.put(p1.getB().getAA(), p1);

20                             p1.getB().setAA(null);// 去除对象a的强引用
21                             a = null;// 去除对象a的强引用,并让垃圾收集器回收AA对象在堆中的内存
22                             System.gc();

23                             Iterator i = weakMap1.entrySet().iterator();

24                            while (i.hasNext()) {

25                                        Map.Entry en = (Map.Entry) i.next();

26                                        System.out.println("weakMap:" + en.getKey() + ":" + en.getValue());

27                                      }

28                            }

29         }

30
31     class AA {

32             private String a;

33
34              public AA(String a) {

35                       this.a = a;

36             }

37
38             public String getA() {

39                        return a;

40             }

41
42             public void setA(String a) {

43                      this.a = a;

44            }

45    }

46
47    class BB {

48            private AA a;

49
50             public BB(AA a) {

51                       this.a = a;

52             }

53
54             public AA getAA() {

55                      return a;

56            }

57
58             publicvoid setAA(AA a) {

59                              this.a = a;

60           }

61   }

62
63    class People1 {

64              private BB b;

65
66              public People1(BB b) {

67                       this.b = b;

68            }

69
70              public BB getB() {

71                      return b;

72             }

73
74             publicvoid setB(BB b) {

75                      this.b = b;

76              }

77    }

 

 1 package com.froest.excel; 2  3 import java.util.Iterator; 4 import java.util.Map; 5 import java.util.WeakHashMap; 6  7 public class Test5 { 8  9   /**10    * @param args11    */12   public static void main(String[] args) {13     // TODO Auto-generated method stub14     WeakHashMap<AA, People1> weakMap1 = new WeakHashMap<AA, People1>();15     String b = new String("louhang1");16     AA a = new AA(b);17     BB bb = new BB(a);18     People1 p1 = new People1(bb);19     weakMap1.put(p1.getB().getAA(), p1);20     p1.getB().setAA(null);// 去除对象a的强引用21     a = null;// 去除对象a的强引用,并让垃圾收集器回收AA对象在堆中的内存22     System.gc();23     Iterator i = weakMap1.entrySet().iterator();24     while (i.hasNext()) {25       Map.Entry en = (Map.Entry) i.next();26       System.out.println("weakMap:" + en.getKey() + ":" + en.getValue());27     }28   }29 }30 31 class AA {32   private String a;33 34   public AA(String a) {35     this.a = a;36   }37 38   public String getA() {39     return a;40   }41 42   public void setA(String a) {43     this.a = a;44   }45 }46 47 class BB {48   private AA a;49 50   public BB(AA a) {51     this.a = a;52   }53 54   public AA getAA() {55     return a;56   }57 58   public void setAA(AA a) {59     this.a = a;60   }61 }62 63 class People1 {64   private BB b;65 66   public People1(BB b) {67     this.b = b;68   }69 70   public BB getB() {71     return b;72   }73 74   public void setB(BB b) {75     this.b = b;76   }77 }

View Code

  运行上面代码以后没有输出任何结果,说明,WeakHashMap中的键值对已经被回收了,如果注释掉p1.getB().setAA(null);或者a = null;这2行中的任意一行都没法清除WeakhashMap中的键值对。
  在WeakHashMap的get(),put()函数中的getTable()方法会调用expungeStateEntries方法,以清理持有弱引用的key的表项。exPungeStateEntries方法源代码:

1  private void expungeStaleEntries() {
 2                     Entry<K,V> e;
 3                    while ( (e = (Entry<K,V>) queue.poll()) !=null) {
 4                             int h = e.hash;
 5                             int i = indexFor(h, table.length);
 6
7                               Entry<K,V> prev = table[i];
 8                              Entry<K,V> p = prev;
 9                             while (p != null) {
10                                      Entry<K,V> next = p.next;
11                                     if (p == e) {
12                                         if (prev == e)
13                                              table[i] = next;
14                                         else
15                                              prev.next = next;
16                                          e.next =null// Help GC
17                                          e.value =null; // " "
18                                          size--;
19                                         break;
20                                   }
21                                    prev = p;
22                                    p = next;
23                           }
24                   }
25     }

 1 private void expungeStaleEntries() { 2     Entry<K,V> e; 3         while ( (e = (Entry<K,V>) queue.poll()) != null) { 4             int h = e.hash; 5             int i = indexFor(h, table.length); 6  7             Entry<K,V> prev = table[i]; 8             Entry<K,V> p = prev; 9             while (p != null) {10                 Entry<K,V> next = p.next;11                 if (p == e) {12                     if (prev == e)13                         table[i] = next;14                     else15                         prev.next = next;16                     e.next = null;  // Help GC17                     e.value = null; //  "   "18                     size--;19                     break;20                 }21                 prev = p;22                 p = next;23             }24         }25     }

View Code

 在第二个while循环中会移除已经被回收的表项。

0 0