浅谈Java的WeakHashMap源码

 更新时间:2023年09月07日 11:15:50   作者:QZero_0  
这篇文章主要介绍了浅谈Java的WeakHashMap源码,WeakHashMap,从名字可以看出它是某种 Map,它的特殊之处在于 WeakHashMap 里的entry可能会被GC自动删除,即使程序员没有调用remove()或者clear()方法,需要的朋友可以参考下

WeakHashMap源码解析

JDK版本

JDK 1.8.0_110

总体介绍

介绍一个特殊的成员: WeakHashMap,从名字可以看出它是某种 Map。

它的特殊之处在于 WeakHashMap 里的 entry 可能会被GC自动删除,即使程序员没有调用 remove() 或者 clear() 方法。

更直观的说,当使用 WeakHashMap 时,即使没有显示的添加或删除任何元素,也可能发生如下情况:

  • 调用两次size()方法返回不同的值;
  • 两次调用isEmpty()方法,第一次返回false,第二次返回true;
  • 两次调用containsKey()方法,第一次返回true,第二次返回false,尽管两次使用的是同一个key;
  • 两次调用get()方法,第一次返回一个value,第二次返回null,尽管两次使用的是同一个对象。

遇到这么奇葩的现象,是不是觉得使用者一定会疯掉?

其实不然,WeakHashMap的这个特点特别适用于需要缓存的场景。

在缓存场景下,由于内存是有限的,不能缓存所有对象;对象缓存命中可以提高系统效率,但缓存MISS也不会造成错误,因为可以通过计算重新得到。

要明白 WeakHashMap 的工作原理,还需要引入一个概念 : 弱引用(WeakReference)。

我们都知道Java中内存是通过GC自动管理的,GC会在程序运行过程中自动判断哪些对象是可以被回收的,并在合适的时机进行内存释放。

GC判断某个对象是否可被回收的依据是,是否有有效的引用指向该对象。如果没有有效引用指向该对象(基本意味着不存在访问该对象的方式),那么该对象就是可回收的。这里的有效引用 并不包括弱引用。

也就是说,虽然弱引用可以用来访问对象,但进行垃圾回收时弱引用并不会被考虑在内,仅有弱引用指向的对象仍然会被GC回收。

WeakHashMap 内部是通过弱引用来管理 entry 的,弱引用的特性对应到 WeakHashMap 上意味着什么呢?

将一对 key, value 放入到WeakHashMap里并不能避免该 key 值被GC回收,除非在 WeakHashMap之外还有对该 key 的强引用。

Java中引用也是分种类的,并且不同种类的引用对GC的影响不同就够了。

具体实现

WeakHashMap的存储结构类似于Map

Weak HashSet

Java Collections工具类给出了解决方案, Collections.newSetFromMap(Map<E,Boolean> map) 方法可以将任何 Map包装成一个Set。

通过如下方式可以快速得到一个 Weak HashSet:

// 将WeakHashMap包装成一个Set
Set<Object> weakHashSet = Collections.newSetFromMap(
        new WeakHashMap<Object, Boolean>());

不出所料, newSetFromMap() 方法只是对传入的 Map做了简单包装:

// Collections.newSetFromMap()用于将任何Map包装成一个Set
public static <E> Set<E> newSetFromMap(Map<E, Boolean> map) {
    return new SetFromMap<>(map);
}
private static class SetFromMap<E> extends AbstractSet<E>
    implements Set<E>, Serializable
{
    private final Map<E, Boolean> m;  // The backing map
    private transient Set<E> s;       // Its keySet
    SetFromMap(Map<E, Boolean> map) {
        if (!map.isEmpty())
            throw new IllegalArgumentException("Map is non-empty");
        m = map;
        s = map.keySet();
    }
    public void clear()               {        m.clear(); }
    public int size()                 { return m.size(); }
    public boolean isEmpty()          { return m.isEmpty(); }
    public boolean contains(Object o) { return m.containsKey(o); }
    public boolean remove(Object o)   { return m.remove(o) != null; }
    public boolean add(E e) { return m.put(e, Boolean.TRUE) == null; }
    public Iterator<E> iterator()     { return s.iterator(); }
    public Object[] toArray()         { return s.toArray(); }
    public <T> T[] toArray(T[] a)     { return s.toArray(a); }
    public String toString()          { return s.toString(); }
    public int hashCode()             { return s.hashCode(); }
    public boolean equals(Object o)   { return o == this || s.equals(o); }
    public boolean containsAll(Collection<?> c) {return s.containsAll(c);}
    public boolean removeAll(Collection<?> c)   {return s.removeAll(c);}
    public boolean retainAll(Collection<?> c)   {return s.retainAll(c);}
    // addAll is the only inherited implementation
    ......
}

到此这篇关于浅谈Java的WeakHashMap源码的文章就介绍到这了,更多相关WeakHashMap源码内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Java中实现将jar包内文件资源释放出来

    Java中实现将jar包内文件资源释放出来

    这篇文章主要介绍了Java中实现将jar包内文件资源释放出来的方法,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-08-08
  • springMvc异步的DeferredResult long polling应用示例解析

    springMvc异步的DeferredResult long polling应用示例解析

    这篇文章主要为大家介绍了springMvc中DeferredResult的long polling应用示例解析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-03-03
  • ava实现一致性Hash算法

    ava实现一致性Hash算法

    本文主要详细介绍了Java如何实现一致性Hash算法,其实现原理将key映射到 2^32 - 1 的空间中,将这个数字的首尾相连,形成一个环。想了解更多的同学,可以参考本文
    2023-03-03
  • SpringBoot实现给属性赋值的两种方式

    SpringBoot实现给属性赋值的两种方式

    在Spring Boot中,配置文件是用来设置应用程序的各种参数和操作模式的重要部分,Spring Boot支持两种主要类型的配置文件:properties文件和YAML 文件,这两种文件都可以用来定义相同的配置,接下来由小编给大家详细的介绍一下这两种方式
    2024-07-07
  • springmvc处理异步请求的示例

    springmvc处理异步请求的示例

    这篇文章主要介绍了springmvc处理异步请求的示例,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-01-01
  • Java Io File文件操作基础教程

    Java Io File文件操作基础教程

    这篇文章主要介绍了Java Io File文件操作,在这里需要注意File只能访问文件以及文件系统的元数据。如果你想读写文件内容,需要使用FileInputStream、FileOutputStream或者RandomAccessFile,需要的朋友可以参考下
    2022-05-05
  • SpringBoot中使用拦截器的配置详解

    SpringBoot中使用拦截器的配置详解

    这篇文章主要介绍了SpringBoot中使用拦截器的配置详解,拦截器是 AOP 的一种实现,专门拦截对动态资源的后台请求,即拦截对控制层的请 求,使用场景比较多的是判断用户是否有权限请求后台,需要的朋友可以参考下
    2024-01-01
  • Java DriverManager.getConnection()获取数据库连接

    Java DriverManager.getConnection()获取数据库连接

    这篇文章主要介绍了Java DriverManager.getConnection()获取数据库连接,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-01-01
  • itext生成PDF设置页眉页脚的实例详解

    itext生成PDF设置页眉页脚的实例详解

    这篇文章主要介绍了itext生成PDF设置页眉页脚的实例详解的相关资料,希望通过本文能帮助到大家,需要的朋友可以参考下
    2017-09-09
  • Java跨模块调用方式

    Java跨模块调用方式

    这篇文章主要介绍了Java跨模块调用方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-08-08

最新评论