Weak Reference Soft Reference Phantom Reference

JAVA 中的引用

JAVA 中存在4种引用,由强到弱依次是强引用、软引用、弱引用、虚引用。

  • 强引用(Strong Reference):通常我们通过 new 创建一个对象的时候返回的引用就是强引用。若一个对象通过一系列强引用是可达的,那么这个对象就是强可达的,它就不会被垃圾回收。
  • 软引用(Soft Reference):软引用和弱引用的区别在于,若一个对象只是弱引用可达的,那么不论内存是否充足,该对象都会被回收。然而若一个对象只是软引用可达的,那么只有在内存不充足的时候该对象才会被回收。因此软引用要比弱引用要强一些。软引用可以用来实现内存敏感的高速缓存。

软引用在实际中有重要的应用,例如浏览器的后退按钮。按后退时,这个后退按钮对应的网页内容是重新进行请求还是从缓存中取出呢?这就要看具体的实现策略了。

  1. 如果一个网页在浏览结束时就进行内容的回收,则按后退查看前面浏览过的页面时,需要重新请求构建。
  2. 如果将浏览过的网页存储到内存中可能会造成内存的大量浪费,甚至会造成内存溢出
    这时候就可以使用软引用。
Page prev = new Page(); // 获取页面进行浏览
SoftReference softRef = new SoftReference(prev); // 浏览完毕置为软引用
if (softRef.get() != null) {
   prev = softRef.get(); // 还没有被垃圾收集器回收,直接获取。
} else {
   prev = new Page(); // 由于内存吃紧,页面已被回收,重新构建。
   softRef = new SoftReference(prev); // 重新放进软引用
}
  • 弱引用(Weak Reference):弱引用对象的存在不会阻止它所指向的对象被垃圾回收。假设垃圾收集器在某个时间点决定一个对象是弱可达的(weakly reachable)(也就是说当前指向它的全部都是弱引用),这时垃圾收集器会清除所有指向该对象的弱引用,然后把这个对象标记为可终结(finalizable)的,这样它随后就会被回收。与此同时或稍后,垃圾收集器会把那些刚清除的弱引用放入引用队列(Reference Queue,在创建弱引用对象时指定)中。
  • 虚引用(Phantom Reference):虚引用是 JAVA 中最弱的引用,它弱到什么程度呢?它是如此弱,以至于我们通过虚引用甚至无法获取到被引用的对象,虚引用存在的唯一作用就是当它指向的对象被回收的时候,虚引用本身会被加入到引用队列中,用作记录它所指向的对象已被回收。虚引用与软引用和弱引用的一个区别在于:虚引用必须和引用队列 (ReferenceQueue)联合使用。当垃圾回收器准备回收一个对象时,如果发现它还有虚引用,就会在回收对象的内存之前,把这个虚引用加入到与之关联的引用队列中。
    虚引用主要用于跟踪对象被垃圾回收的状态,通过查看引用队列中是否包含对象所对应的虚引用来判断它是否即将被垃圾回收,从而采取行动,它并不被期待用来取得目标对象。Cleaner 就是一个虚引用的例子。

引用队列

实际上,WeakReference 有两个构造函数:

  1. WeakReference(T referent)
  2. WeakReference(T referent, ReferenceQueue q)

我们可以看到第二个构造方法中提供了一个ReferenceQueue类型的参数,通过提供这个参数,我们便把创建的弱引用对象注册到这个引用队列上,这样当该弱引用对象被垃圾回收器回收时,就会把它插入到引用队列中,我们便可以对这些被清除的弱引用对象进行统一管理(一般是做资源清除工作)。

WeakHashMap

WeakHashMap 内部是通过弱引用来管理 entry 的,弱引用的特性对应到 WeakHashMap 上意味着什么呢?将一对 放入到 WeakHashMap 里并不能避免该 key 值被 GC 回收,除非在 WeakHashMap 之外还有对该key的强引用。

WeakHashMap的要点如下:

  1. 在 WeakHashMap 中,当某个键中的对象不再被正常使用时,将自动移除该条目。更精确地说,对于一个给定的键,其映射的存在并不阻止垃圾回收器对该键的丢弃,这就使该键成为可终止的,被终止,然后被回收。丢弃某个键时,其条目从映射中有效地移除。
  2. WeakHashMap 类的行为部分取决于垃圾回收器的动作。因为垃圾回收器在任何时候都可能丢弃键,WeakHashMap 就像是一个被悄悄移除条目的未知线程。特别地,即使对 WeakHashMap 实例进行同步,并且没有调用任何赋值方法,在一段时间后 size 方法也可能返回较小的值,对于 isEmpty 方法,可能先返回 false,然后返回true,对于给定的键,containsKey 方法可能先返回 true 然后返回 false,对于给定的键,get 方法可能先返回一个值,但接着返回 null,对于以前出现在映射中的键,put 方法返回 null,而 remove 方法返回 false,对于键集合、值集合和条目集合进行的检查,生成的元素数量会越来越少。
  3. WeakHashMap 中的每个键对象间接地存储为一个弱引用的指示对象。因此,不管是在映射内还是在映射之外,只有在垃圾回收器清除某个键的弱引用之后,该键才会自动移除。
  4. 类似于大多数的集合类,该类是并发不安全的,如果想要使用并发安全版本的 WeakHashMap,使用Collections.synchronizedMap(weakHashMap) 进行同步即可。

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

你可能感兴趣的:(Weak Reference Soft Reference Phantom Reference)