理解Java中的弱引用WeakReference

什么是弱引用

弱引用对象的存在不会阻止它所指向的对象被垃圾回收器回收,弱引用最常见的用途是实现规范映射(比如HashMap)。

假设垃圾收集器在某个时间点决定一个对象是弱可达的(weakly reachable)(也就是说当前指向它的全都是弱引用),这时垃圾收集器会清除所有指向该对象的弱引用,然后垃圾收集器会把这个弱可达对象标记为可终结(finalizable)的,这样它们随后就会被收回。与此同进或稍后,垃圾收集器会把那些刚清除的弱引用放入创建弱引用对象时所登记的引用队列中。

1、强引用

通常我们通过new来创建一个新对象返回的引用就是一个强引用,若一个对象通过一系列强引用可到达,它就是强可到达,那么它就不会被回收。

显式地设置为null,或者超出对象的生命周期,此时就可以被垃圾回收器回收。

2、软引用

软引用和弱引用的区别在于,若一个对象是弱引用可达,无论当前内存是否充足它都会被回收,而软引用可达的对象在内存不充足时才会被回收,因此软引用要比弱引用”强“一些。

使用场景:

图片缓存,网页缓存。

3、弱引用

个人理解,在jvm内存有限的情况下,在静态类的集合类中缓存了一些大量数据,而这些数据是有价值的,但构建比较耗时,这种情况下才会使用弱引用。

4、虚引用

是java中最弱的引用,唯一作用就是当它指向的对象被回收后,虚引用本身会被加入到引用队列中,用作记录它指向的对象已被销毁。

为什么使用弱引用

考虑下面的场景:现在有一个Product类代表一种产品,这个类被设计为不可扩展的,而此时我们想要为每个产品增加一个编号。一种解决方案是使用HashMap<Product, Integer>。于是问题来了,如果我们已经不再需要一个Product对象存在于内存中(比如已经卖出了这件产品),假设指向它的引用为productA,我们这时会给productA赋值为null,然而这时productA过去指向的Product对象并不会被回收,因为它显然还被HashMap引用着。所以这种情况下,我们想要真正的回收一个Product对象,仅仅把它的强引用赋值为null是不够的,还要把相应的条目从HashMap中移除。显然“从HashMap中移除不再需要的条目”这个工作我们不想自己完成,我们希望告诉垃圾收集器:在只有HashMap中的key在引用着Product对象的情况下,就可以回收相应Product对象了。显然,根据前面弱引用的定义,使用弱引用能帮助我们达成这个目的。我们只需要用一个指向Product对象的弱引用对象来作为HashMap中的key就可以了。

如何使用

拿上面介绍的场景来说,我们使用一个指向Product对象的弱引用对象来作为Hash的key,只需这样定义这个弱引用对象。

productA = new Product(...);
WeakReference<Product> weakProductA = new WeakReference<>(productA);

现在,若引用对象weakProductA就指向了Product对象productA。那么我们怎么通过weakProduct获取它所指向的Product对象productA呢?

Product product = weakProductA.get();

实际上,对于这种情况,Java类库为我们提供了WeakHashMap类,使用这个类,它的键自然就是弱引用对象,无需我们再手动包装原始对象。这样一来,当productA变为null时,这时指向这个Product对象的就是由弱引用对象weakProductA了,那么显然这个时候相应的Product对象是弱可达的,所以指向它的弱引用会被清除,这个Product对象随即会被回收,指向它的弱引用对象会进入引用队列中。

猜你喜欢

转载自blog.csdn.net/CHS007chs/article/details/85162198