本文主要讲述java.lang.ref.Reference这个类的一些基本概念和使用方法
Reference
// 判断次Reference是否已被回收
public boolean isEnqueued()
// 手动进行回收
public boolean enqueue()
// 去掉对value的引用
public void clear()
java.lang.ref 包中提供了三种主要类型的引用对象:
-
SoftReference
软引用在内存不足时才会被垃圾收集器清除。在内存充足时,软引用指向的对象不会被回收。
用途:适用于实现内存敏感的缓存。 -
WeakReference:弱引用不会阻止其引用的对象被垃圾收集。
常用于实现映射(如 WeakHashMap),不希望引用的对象阻止其被回收。
一旦没有强引用指向该对象,垃圾收集器会立即回收该对象。 -
PhantomReference:虚引用在对象被回收后会被加入到引用队列中,且无法通过 get() 方法访问。
用于管理资源的清理操作。
与软引用和弱引用不同,虚引用不能直接访问其引用的对象。 -
java.lang.ref.FinalReference
当引用的对象被回收时,通过get方法获取到的值就为null,同时还提供了enqueue方法可以手动将引用的值置为null
ReferenceQueue
java.lang.ref.ReferenceQueue
概念:引用队列可以用来监控引用对象的状态。
使用:在创建引用对象时,可以将其注册到一个引用队列中;当其引用的对象被回收时,该引用对象会被加入到引用队列中。
方法:
poll(): 检查队列中是否有可用的引用对象。
remove(): 阻塞直到队列中有引用对象可以移除。
Reference Handler线程
Reference加载时会启动一个名为Reference Handler的后台线程,负责处理与引用对象(如软引用、弱引用和虚引用)相关的任务。
它主要干两件事情
- 处理引用队列:Reference Handler 线程主要负责监控和处理注册到引用队列中的引用对象。
- 清理操作:当某个对象被垃圾收集器回收时,相关的引用对象会被加入到引用队列中,Reference Handler 线程会处理这些引用并执行相应的清理操作。
static {ThreadGroup tg = Thread.currentThread().getThreadGroup();for (ThreadGroup tgn = tg;tgn != null;tg = tgn, tgn = tg.getParent());Thread handler = new ReferenceHandler(tg, "Reference Handler");/* If there were a special system-only priority greater than* MAX_PRIORITY, it would be used here*/handler.setPriority(Thread.MAX_PRIORITY);handler.setDaemon(true);handler.start();// provide access in SharedSecretsSharedSecrets.setJavaLangRefAccess(new JavaLangRefAccess() {@Overridepublic boolean tryHandlePendingReference() {return tryHandlePending(false);}});
}
如下图所示:
引用队列:每个引用对象(如 SoftReference、WeakReference 和 PhantomReference)在创建时可以指定一个引用队列。当这些引用对象的 referent 被回收时,它们会被加入到这个引用队列中。
持续监控:Reference Handler 线程会持续运行,调用 ReferenceQueue 的 remove() 方法,等待引用对象的到来。
执行清理:一旦引用对象被加入到队列,Reference Handler 线程可以读取这些引用并执行相应的清理逻辑,比如释放资源或通知其它组件。
WeakHashMap
https://docs.oracle.com/en/java/javase/15/docs/api/java.base/java/util/WeakHashMap.html
Map.Entry会持续存留在HashMap中
LRU缓存, 例如LinkedHashMap
import java.util.LinkedHashMap;
import java.util.Map;public class LRUCache<K, V> extends LinkedHashMap<K, V> {private final int maxSize;public LRUCache(int maxSize) {super(maxSize, 0.75F, true);this.maxSize = maxSize;}@Overrideprotected boolean removeEldestEntry(Map.Entry<K, V> eldest) {return size() > maxSize;}
}
参考资料
- https://stackoverflow.com/questions/68425363/understanding-weakreferences