HashMap + 软引用进行缓存

一、强引用

强引用的特点:

  1. 可以直接访问目标对象。
  2. 所指向的对象在任何时候都不会被系统回收。JVM宁愿抛出OOM异常,也不会回收强引用所指向的对象。
  3. 可能导致内存泄漏。
//强引用
User user = new User("zhangsan", 18);

二、软引用(SoftReference)与弱引用(WeakReference)

软引用:如果一个对象只具有软引用,而当前虚拟机堆内存空间足够,那么垃圾回收器就不会回收它,反之就会回收这些软引用指向的对象。

弱引用:垃圾回收器一旦发现某块内存上只有弱引用(一定请注意只有弱引用,没强引用),不管当前内存空间是否足够,那么都会回收这块内存。

三、代码实例(强引用VS软引用)

现在的管理系统里,为了提升性能,往往会加入缓存,将部分常用的数据缓存到内存中,这样用于在访问时,会直接从内存中取出,降低数据库的访问量,加快用户获取数据的速度。将数据加入到hashmap中,如果内存空间足够,那么我们可以通过缓存来提升性能,但万一内存空间不够,我们可以依次释放一些内存,释放后不会影响业务流程,最多就是降低些性能。

对比一下,如果我们这里不用软应用,而是用强引用来缓存,由于不知道用户何时点击,我们还无法得知什么时候可以撤销这些对象上的强引用,或者即使我们引入了一套缓存淘汰流程,但这就是额外的工作了,这就没刚才使用“软引用“那样方便了。

1、软引用hashmap工具类

public class SoftHashMap extends HashMap {
 
    /**
     * queue,软引用标记队列
     * 

* ★★★★★★★ 解释 ★★★★★★★ * 当SoftNode中 Value 被回收时,SoftNode 对象会被放入 queue中,以表示当前SoftNode 中的Value不存在 * 对我们的使用好处就是,我们读取 queue 队列,取出 SoftNode对象,取出其内部的 Key * 以便于 temp 通过 key remove */ private ReferenceQueue queue; /** * 真正的map对象 * 1、temp 内部 封装的 Node 强引用 K 和 SoftNode * 2、SoftNode 内部强引用K,弱引用真正的Value */ private HashMap> temp; public SoftHashMap() { queue = new ReferenceQueue<>(); temp = new HashMap<>(); } @Override public V get(Object key) { clearQueue(); // 通过 key进行取值,如果为null,返回null,否则返回 SoftNode 软引用的值 SoftNode softNode = temp.get(key); return softNode == null ? null : (V) softNode.get(); } @Override public V put(K key, V value) { clearQueue(); // 创建 SoftNode对象 SoftNode softNode = new SoftNode(key, value, queue); // 返回key之前所对应的SoftNode对象,即oldSoftNode SoftNode oldSoftNode = temp.put(key, softNode); // 如果oldSoftNode为null,就返回null,否则就返回 oldSoftNode所软引用的 Value return oldSoftNode == null ? null : (V) oldSoftNode.get(); } @Override public boolean containsKey(Object key) { clearQueue(); return temp.containsKey(key); } @Override public V remove(Object key) { clearQueue(); SoftNode remove = temp.remove(key); return remove == null ? null : remove.get(); } @Override public int size() { clearQueue(); return temp.size(); } /** * 通过软引用队列内的 SoftNode,获取Key,然后temp 清除此 Key * @see ReferenceQueue poll() * poll() -- 类似于 stack 的pop(),移除并返回此对象 */ private void clearQueue() { SoftNode poll; while ((poll = (SoftNode) queue.poll()) != null) { temp.remove(poll.key); } } /** * 对V进行软引用的类 * @param key,用于当 V 被回收后,temp 可以通过 key 进行移除 * @param Value,真正的值 * * 传入的queue,用于当Value被回收后,将 SoftNode对象放入 queue中, * 以便于表示 某 SoftNode对象中的Value 已经被收回了。 */ private class SoftNode extends SoftReference { K key; public SoftNode(K k, V v, ReferenceQueue queue) { super(v, queue); key = k; } } }

2、强引用与软引用的测试对比:

HashMap + 软引用进行缓存_第1张图片

HashMap + 软引用进行缓存_第2张图片 测试中可以明显的看到:

  1. 强引用时,加载的String更多,但会造成内存溢出;
  2. 弱引用时,由于弱引用的机制(内存满时会进行垃圾回收),不会造成内存溢出,但由于需要对String进行处理,所以加载的String没有强引用时多;

 

往期精彩内容:

超详细的springBoot学习笔记

Java多线程基础知识总结(绝对经典)

Java面试题总结(附答案)

Vue基础知识总结(绝对经典)

常见数据结构与算法整理总结

 

你可能感兴趣的:(Java,SE)