带有条件/超时的弱引用

8

在Java中,是否可以创建一个弱引用,当指定的条件返回true时,只有对象可以被发送到垃圾收集器?

假设我有一个类似缓存的东西,它将ID号映射到一些数据:

Map<Integer, SomeData> cache = new HashMap<>();
SomeData 类有两个重要的方法 - void updateTime(),它只是将内部变量设置为当前时间;boolean canBeDeleted(),它检查对象在过去10分钟内是否被使用(通过比较当前时间和保存的时间加上10分钟)。如果未在此一定时间内使用,该方法返回true,并且可以从缓存中移除该对象...。
然而,当我使用弱引用而不是强引用创建缓存时:
Map<Integer, WeakReference<SomeData>> cache = new HashMap<>();

那么,WeakReference 唯一检查的可能是对对象的强引用。但如果它也检查我的条件 canBeDeleted() 并且返回 false,则不应删除引用。是否有方法可以实现这一点?

此外,还存在内存泄漏问题,我不确定该如何解决...当 WeakReference 中的对象被删除时,映射仍包含不必要的键值对。

先谢谢了。


如果您查看Guava 缓存,您可以创建一个自动删除在给定时间内未被引用的条目的缓存。 - Keppil
对于问题中的"()":您仍需要清理地图。删除WeakRef的客户端不会自动删除地图条目。 - Fildor
2个回答

2

您可以使用LinkedHashMap#removeEldestEntry方法,尽管该方法不提供按照缓存中条目存在的时间来删除条目的方式,但它确实提供了一种根据条目是否被访问过来删除条目的方法。

每当添加新条目时,它都提供给实现者一个机会来删除最老的条目。如果该映射表示缓存,则这非常有用:它允许映射通过删除过期条目来减少内存消耗。

protected boolean removeEldestEntry(Map.Entry<K,V> eldest) {
  return size() > limit;

还要记住,您需要使用true初始化LinkedHashMap的accessOrder

accessOrder - 排序模式 - true表示访问排序,false表示插入排序。

因此,将所有内容放在一起,源代码应如下所示:

public class Cache<K, V> extends LinkedHashMap<K, V> {
    private final int MAX_ENTRIES = 100;
    public Cache() {
        super(16, 0.75f, true);// accessOrder is true
    }
    @Override
    protected boolean removeEldestEntry(Map.Entry<K, V> eldest) {
        return size() > MAX_ENTRIES;
    }
}

0

你可以在条件成立的情况下从缓存中删除键。


2
我知道,但接下来我需要有一个单独的线程,例如每10分钟遍历缓存并删除所有不必要的内容。但我更愿意避免另一个线程,并通过与垃圾回收器的某种合作方式完成此操作,如果可能的话。 - Martin Majer
如果你想检查条件是否返回true,无论如何都需要通过缓存进行。你想要实现什么目标还不太清楚。 - Marko Topolnik

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接