今天一起来看下java.util包里的WeakHashMap工具类。
WeakHashMap的定义如下:
public class WeakHashMap<K,V>
extends AbstractMap<K,V>
implements Map<K,V>
简单来说,WeakHashMap实现了Map接口,基于hash-table实现,在这种Map中,key的类型是WeakReference。如果对应的key被回收,则这个key指向的对象会被从Map容器中移除。
WeakHashMap跟普通的HashMap不同,WeakHashMap的行为一定程度上基于垃圾收集器的行为,因此一些Map数据结构对应的常识在WeakHashMap上会失效——size()方法的返回值会随着程序的运行变小,isEmpty()方法的返回值会从false变成true等等。
强引用、软引用和弱引用
“引用”,在Java中指的是一个对象对另一对象的使用(指向)。WeakHashMap中的键的类型是WeakReference,在Java中还有另外两种引用:强引用(Strong Reference)、软引用(Soft Reference)。
强引用
被强引用指向的对象,绝对不会被垃圾收集器回收。Integer prime = 1;
,这个语句中prime对象就有一个强引用。
软引用
被SoftReference指向的对象可能会被垃圾收集器回收,但是只有在JVM内存不够的情况下才会回收;如下代码可以创建一个软引用:
Integer prime = 1;
SoftReference<Integer> soft = new SoftReference<Integer>(prime);
prime = null;
弱引用
当一个对象仅仅被WeakReference引用时,在下个垃圾收集周期时候该对象就会被回收。我们通过下面代码创建一个WeakReference:
Integer prime = 1;
WeakReference<Integer> soft = new WeakReference<Integer>(prime);
prime = null;
当把prime赋值为null的时候,原prime对象会在下一个垃圾收集周期中被回收,因为已经没有强引用指向它。
利用WeakHashMap实现内存缓存
可以看出,WeakHashMap的这种特性比较适合实现类似本地、堆内缓存的存储机制——缓存的失效依赖于GC收集器的行为。假设一种应用场景:我们需要保存一批大的图片对象,其中values是图片的内容,key是图片的名字,这里我们需要选择一种合适的容器保存这些对象。
使用普通的HashMap并不是好的选择,这些大对象将会占用很多内存,并且还不会被GC回收,除非我们在对应的key废弃之前主动remove掉这些元素。WeakHashMap非常适合使用在这种场景下,下面的代码演示了具体的实现:
WeakHashMap<UniqueImageName, BigImage> map = new WeakHashMap<>();
BigImage bigImage = new BigImage("image_id");
UniqueImageName imageName = new UniqueImageName("name_of_big_image"); //强引用
map.put(imageName, bigImage);
assertTrue(map.containsKey(imageName));
imageName = null; //map中的values对象成为弱引用对象
System.gc(); //主动触发一次GC
await().atMost(10, TimeUnit.SECONDS).until(map::isEmpty);
首先,创建一个WeakHashMap对象来存储BigImage实例,对应的key是UniqueImageName对象,保存到WeakHashMap里的时候,key是一个弱引用类型。
然后,我们将imageName设置为null,这样就没有其他强引用指向bigImage对象,按照WeakHashMap的规则,在下一次GC周期中会回收bigImage对象。
通过System.gc()
主动触发一次GC过程,然后可以发现WeakHashMap成为空的了。
总结
本文从WeakHashMap的定义讲起,又通过介绍Java中的三种引用类型来理解WeakHashMap的工作原理,最后利用一个存储大对象的例子演示了WeakHashMap的应用场景。本文中提到的代码,可以在GitHub工程看到。
参考资料
今天的文章Java中的WeakHashMap分享到此就结束了,感谢您的阅读。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/19087.html