引用队列(ReferenceQueue)作用
Queue的意义在于我们在外部可以对queue中的引用进行监控,当引用中的对象被回收后,我们可以对引用对象本身继续做一些清理操作,因为我们引用对象(softRef)也占有一定的资源。
弱引用(WeakReference)
弱引用中的对象具有很短的声明周期,因为在系统GC时,只要发现弱引用,不管堆空间是否足够,都会将对象进行回收。由于垃圾回收器是一个优先级很低的线程,因此不一定会很快发现那些只具有弱引用的对象。
弱引用的简单使用:
Object obj = new Object();
WeakReference weakRef = new WeakReference(obj);
//删除强引用
obj = null;
System.out.println("gc之后的值:" + weakRef.get()); // 对象依然存在
//调用gc
System.gc();
System.out.println("gc之后的值:" + weakRef.get()); // 对象为null
弱引用也可以和一个引用队列联合使用,如果弱引用中的对象(obj)被回收,那么软引用会被 JVM 加入关联的引用队列中。
ReferenceQueue queue &#61; new ReferenceQueue<>();
Object obj &#61; new Object();
WeakReference weakRef &#61; new WeakReference(obj,queue);
//删除强引用
obj &#61; null;
System.out.println("gc之后的值: " &#43; weakRef.get()); // 对象依然存在
//调用gc
System.gc();
//如果obj被回收&#xff0c;则软引用会进入引用队列
Reference> reference &#61; queue.remove();
if (reference !&#61; null){
System.out.println("对象已被回收: "&#43; reference.get()); // 对象为null
}
软引用和弱引用都非常适合保存那些可有可无的缓存数据&#xff0c;当内存不足时&#xff0c;缓存数据被回收(再通过备选方案查询)&#xff0c;当内存充足时&#xff0c;也可以存在较长时间&#xff0c;起到加速的作用。
应用
WeakHashMap
当key只有弱引用时&#xff0c;GC发现后会自动清理键和值&#xff0c;作为简单的缓存表解决方案。
ThreadLocal
ThreadLocal.ThreadLocalMap.Entry 继承了弱引用&#xff0c;key为当前线程实例&#xff0c;和WeakHashMap基本相同。
虚引用(PhantomReference)
虚引用 就是 形同虚设 &#xff0c;它并不能决定 对象的生命周期。任何时候这个只有虚引用的对象都有可能被回收。因此&#xff0c;虚引用主要用来跟踪对象的回收&#xff0c;清理被销毁对象的相关资源。PhantomReference的 get() 方法永远返回null &#xff0c;而且只提供了与引用队列同用的构造函数。所以虚引用必须和引用队列一同使用。
Map map &#61; new HashMap<>();
ReferenceQueue queue &#61; new ReferenceQueue<>();
Object obj &#61; new Object();
PhantomReference phantomRef &#61; new PhantomReference(obj,queue);
map.put(obj,"obj val");
new CheckRefQueue(queue,map).start();
//删除强引用
obj &#61; null;
Thread.sleep(1000);
int i &#61; 1;
while (true){
System.out.println("第"&#43;i&#43;"次gc");
System.gc();
Thread.sleep(1000);
}
public class CheckRefQueue extends Thread {
private ReferenceQueue queue;
private Map map;
public CheckRefQueue(ReferenceQueue queue, Map map) {
this.queue &#61; queue;
this.map &#61; map;
}
&#64;Override
public void run() {
// 等待&#xff0c;直到对象呗回收
Reference reference &#61; queue.remove();
// 释放引用对象的引用
map.remove(reference.get());
}
}
总结
reference-level.png
作者&#xff1a;码上实战
链接&#xff1a;https://www.jianshu.com/p/ee4363989022
来源&#xff1a;简书
著作权归作者所有。商业转载请联系作者获得授权&#xff0c;非商业转载请注明出处。