一文带你了解WeakHashMap

àì夳堔傛蜴生んèń 2023-02-21 06:38 102阅读 0赞

1. WeakHashMap的适用场景

大部分的缓存都需要占用内存,考虑到内存的有限性,并不能缓存所有的对象,此时就需要用到另类的集合,例如WeakHashMap,可以保存一些对象的同时淘汰另一些对象,以此减少存储成本。

2. 什么是WeakHashMap

WeakHashMap,是在HashMap的基础上多了Weak。表示这是一个弱引用的HashMap。

来看下WeakHashMap的类定义:

  1. public class WeakHashMap<K,V>
  2. extends AbstractMap<K,V>
  3. implements Map<K,V> {

那WeakHashMap和HashMap有什么区别呢?

3. WeakHashMap和HashMap的区别

在比较WeakHashMap和HashMap的区别之前,先来讲一下弱引用(WeakReference)

关于弱引用

Java有4种引用,强引用(Strong),弱引用(Weak),软引用(soft),虚引用(phantom)。

弱引用表示一个非必需的对象,强度低于软引用,需要通过WeakReference类来间接引用目标对象。被弱引用关联的对象只能存活到下一次垃圾回收发生之前,当触发垃圾回收时,无论当前内存是否足够,都会回收掉只被弱引用关联的对象

注意:如果这个对象还被强引用所引用,那么就不会被回收

简单了解了弱引用之后,我们做一个
总结:
区别于HashMap的强键,WeakHashMap是弱键。
弱键的作用是随时可能被垃圾回收器回收。

4. WeakHashMap的实现原理

主要通过WeakReference和ReferenceQueue实现

来看下源码:

  1. /** * The entries in this hash table extend WeakReference, using its main ref * field as the key. */
  2. private static class Entry<K,V> extends WeakReference<Object> implements Map.Entry<K,V> {
  3. V value;
  4. final int hash;
  5. Entry<K,V> next;
  6. /** * Creates new entry. */
  7. Entry(Object key, V value,
  8. ReferenceQueue<Object> queue,
  9. int hash, Entry<K,V> next) {
  10. super(key, queue);
  11. this.value = value;
  12. this.hash = hash;
  13. this.next = next;
  14. }
  15. @SuppressWarnings("unchecked")
  16. public K getKey() {
  17. return (K) WeakHashMap.unmaskNull(get());
  18. }
  19. public V getValue() {
  20. return value;
  21. }
  22. public V setValue(V newValue) {
  23. V oldValue = value;
  24. value = newValue;
  25. return oldValue;
  26. }
  1. 新建WeakHashMap,将Entry添加到WeakHashMap中,通过数组table保存Entry。
  2. 弱键在没有被强引用引用的前提下,下一次GC将回收该弱键并添加到ReferenceQueue(queue)队列中。
  3. 再一次操作WeakHashMap时,会先同步table和queue。table中保存了全部的entry,queue中保存被GC回收的entry;同步它们,就是删除table中被GC回收的键值对。

    /* Expunges stale entries from the table. */

    1. private void expungeStaleEntries() {
    2. for (Object x; (x = queue.poll()) != null; ) {
    3. synchronized (queue) {
    4. @SuppressWarnings("unchecked")
    5. Entry<K,V> e = (Entry<K,V>) x;
    6. int i = indexFor(e.hash, table.length);
    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. // Must not null out e.next;
    17. // stale entries may be in use by a HashIterator
    18. e.value = null; // Help GC
    19. size--;
    20. break;
    21. }
    22. prev = p;
    23. p = next;
    24. }
    25. }
    26. }
    27. }

WeakHashMap中的大部分操作都会调用expungeStaleEntries()这个方法,储存被gc回收对象的queue会接收gc发送的回收消息,将queue中的key所对应的value赋值null,帮助完成对Entry的回收工作。

发表评论

表情:
评论列表 (有 0 条评论,102人围观)

还没有评论,来说两句吧...

相关阅读

    相关 了解云HIS

    一、简介   基于云计算技术的B/S架构的HIS系统,为基层医院机构提供标准化的、信息化的、可共享的医疗信息管理系统,实现医患事务管理和临床诊疗管理等标准管理信息系统的

    相关 了解云原生

    > 文章转载于百度百家号:AI课工场 自进入云计算时代后,大量的新概念、新技术如雨后春笋般的涌现出来,从早期的openstack、IAAS平台,到中期的容器技术、微服务架构,