WeakHashMap理解

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

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

  

  这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 public class Test5 {
 8 
 9   /**
10    * @param args
11    */
12   public static void 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   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     }
View Code
复制代码

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

posted on   Kahuna  阅读(12858)  评论(0编辑  收藏  举报

编辑推荐:
· AI与.NET技术实操系列:使用Catalyst进行自然语言处理
· 分享一个我遇到过的“量子力学”级别的BUG。
· Linux系列:如何调试 malloc 的底层源码
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
阅读排行:
· 几个技巧,教你去除文章的 AI 味!
· 系统高可用的 10 条军规
· 关于普通程序员该如何参与AI学习的三个建议以及自己的实践
· 对象命名为何需要避免'-er'和'-or'后缀
· 使用Avalonia/C#构建一个简易的跨平台MCP客户端
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

导航

统计

点击右上角即可分享
微信分享提示