public class WeakHashMap extends AbstractMap implements Map {
// 使用弱引用作为Entry的key
private static class Entry extends WeakReference implements Map.Entry {
V value;
int hash;
Entry next;
Entry(K key, V value, ReferenceQueue queue, int hash, Entry next) {
super(key, queue); // key被弱引用持有
this.value = value;
this.hash = hash;
this.next = next;
}
}
}
4.4 缓存示例
public class WeakCache {
private final Map<K, WeakReference> cache = new HashMap();
public void put(K key, V value) {
cache.put(key, new WeakReference(value));
}
public V get(K key) {
WeakReference ref = cache.get(key);
return ref != null ? ref.get() : null;
}
// 定期清理null值的WeakReference
public void cleanUp() {
cache.entrySet().removeIf(entry ->
entry.getValue() == null || entry.getValue().get() == null);
}
}
4.5 回收测试
public class WeakReferenceDemo {
public static void main(String[] args) {
WeakReference
五、虚引用(PhantomReference)
5.1 基本概念
虚引用是最弱的引用类型,无法通过它获取对象实例,主要用于跟踪对象被回收的状态。
ReferenceQueue
5.2 特点
不可达性:get()始终返回null
回收通知:通过ReferenceQueue获得回收通知
使用场景:精细化的对象回收后处理
5.3 实现原理
public class PhantomReference extends Reference {
public T get() {
return null; // 始终返回null
}
public PhantomReference(T referent, ReferenceQueue q) {
super(referent, q);
}
}
5.4 资源清理示例
public class ResourceCleaner {
private static final ReferenceQueue queue = new ReferenceQueue();
private static final List references = new ArrayList();
public static void register(Object resource, Runnable cleanupAction) {
references.add(new CleanupReference(resource, cleanupAction, queue));
}
public static void cleanup() {
CleanupReference ref;
while ((ref = (CleanupReference) queue.poll()) != null) {
ref.cleanup();
references.remove(ref);
}
}
private static class CleanupReference extends PhantomReference {
private final Runnable cleanupAction;
CleanupReference(Object referent, Runnable cleanupAction, ReferenceQueue q) {
super(referent, q);
this.cleanupAction = cleanupAction;
}
void cleanup() {
cleanupAction.run();
}
}
}
5.5 使用示例
public class PhantomReferenceDemo {
public static void main(String[] args) {
Object resource = new Object();
// 注册清理操作
ResourceCleaner.register(resource, () ->
System.out.println("资源被回收,执行清理操作"));
// 取消强引用
resource = null;
// 触发GC
System.gc();
// 处理清理操作
ResourceCleaner.cleanup();
}
}
六、ReferenceQueue的作用
引用队列(ReferenceQueue)与软/弱/虚引用配合使用,主要用途:
跟踪引用状态:当引用对象被回收时,引用本身会被加入队列
执行后续操作:通过轮询队列执行清理工作
避免引用堆积:及时清理无用的Reference对象
6.1 使用模式
ReferenceQueue queue = new ReferenceQueue();
WeakReference ref = new WeakReference(new Object(), queue);
// 在另一个线程中处理队列
new Thread(() -> {
try {
while (true) {
Reference r = queue.remove();
System.out.println("对象被回收: " + r);
// 执行清理操作
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}).start();
6.2 各引用类型与队列
引用类型
入队时机
典型用途
软引用
对象被回收且内存不足
缓存清理通知
弱引用
对象被回收
WeakHashMap维护
虚引用
对象被回收
资源精确释放
七、四种引用的对比总结
7.1 特性对比表
特性
强引用
软引用
弱引用
虚引用
回收强度
不回收
内存不足时回收
下次GC回收
随时可能回收
get()返回值
对象本身
对象本身(回收前)
对象本身(回收前)
始终null
引用队列
不支持
支持
支持
必须配合使用
典型用途
普通对象引用
内存敏感缓存
规范化映射
资源清理跟踪
实现类
-
SoftReference
WeakReference
PhantomReference
7.2 生命周期图示
八、实际应用场景
8.1 缓存实现选择
强引用缓存:
Map cache = new HashMap(); // 可能内存泄漏
软引用缓存:
Map<String, SoftReference> cache = new HashMap(); // 自动释放
弱引用缓存:
Map<String, WeakReference> cache = new HashMap(); // 短期缓存
8.2 监听器管理
public class ListenerManager {
private final Map<EventListener, WeakReference> listeners = new WeakHashMap();
public void addListener(EventListener listener) {
listeners.put(listener, new WeakReference(listener));
}
// 无需显式移除,GC会自动清理
}
8.3 资源清理最佳实践
public class ResourceHolder implements AutoCloseable {
private final Object resource;
private final PhantomReference phantomRef;
public ResourceHolder(Object resource) {
this.resource = resource;
this.phantomRef = new PhantomReference(resource, cleanupQueue);
}
@Override
public void close() {
// 显式清理
cleanupResource(resource);
}
// 防止忘记调用close()
protected void finalize() throws Throwable {
if (resource != null) {
cleanupResource(resource);
}
}
private static void cleanupResource(Object resource) {
// 实际清理逻辑
}
}