【问题标题】:Weak reference with a condition / timeout带有条件/超时的弱引用
【发布时间】:2012-10-19 09:43:35
【问题描述】:

是否可以在 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 中的对象被删除时,映射仍然包含不必要的键/值对)。

提前致谢。

【问题讨论】:

  • 如果您查看Guavas caches,您可以创建一个自动删除在给定时间内未被引用的条目。
  • 对于 "()" 中的问题:你仍然需要清理你的地图。删除 WeakRef 的客户端不会自动删除地图条目。

标签: java garbage-collection weak-references


【解决方案1】:

您可以使用LinkedHashMap#removeEldestEntry 虽然它没有提供根据条目在缓存中的时间量来删除的方法,但它确实提供了一种根据条目是否被访问来删除条目的方法。

它为实施者提供了在每次添加新条目时删除最旧条目的机会。如果映射表示缓存,这很有用:它允许映射通过删除过时的条目来减少内存消耗。

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

还记得你需要用accessOrdertrue初始化LinkedHashMap。

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;
    }
}

【讨论】:

    【解决方案2】:

    您可以只删除条件为真的缓存中的键。

    【讨论】:

    • 我知道,但是我需要一个单独的线程,例如每 10 分钟通过一次缓存并删除所有不必要的内容。但如果可能的话,我宁愿避免使用另一个线程,并通过与垃圾收集器的某种合作来做到这一点。
    • 如果要检查条件是否返回true,无论如何都需要通过缓存。目前还不清楚你想要实现什么。
    猜你喜欢
    • 1970-01-01
    • 2013-05-10
    • 1970-01-01
    • 1970-01-01
    • 2014-08-15
    • 2013-07-06
    • 1970-01-01
    • 1970-01-01
    • 2022-01-23
    相关资源
    最近更新 更多