Java:寻找可变/可重新引用的弱引用实现

4

我正在寻找一种类似于java.lang.ref.WeakReference的弱引用实现,但它提供了一个set()方法或其他重新引用创建的弱引用对象的方式。下面是一个例子:

MutableWeakReference ref = new MutableWeakReference(someObject);
ref.set(anotherObject);

我需要这样做是为了避免对象的创建,因为在我的情况下,不断改变弱引用所指向的对象会使执行时间慢了一个数量级。我尝试从JDK中复制代码,但似乎不可能,因为java.lang.ref.Reference使用了内部的sun.misc.Cleaner类。我也查看了Android实现,但它似乎依赖于Dalvik VM进行垃圾回收。我想知道是否可以在不更改JVM/环境的情况下实现这一点。

2
如果您经常更改引用,那么保留它一段时间,只有在其过期时才获取新的“WeakReference”如何? - Tom Hawtin - tackline
4
如果弱引用(WeakReference)的参照对象是可变的,可能会出现竞争条件,即在放置在引用队列(ReferenceQueue)后突然更改了引用。我认为这不是正确的做法。 - Ron
3个回答

3

你是否可以将引用封装在一个简单的

class MyOwnReference<T> {
    public T ref;
    public void set(T o) { ref = o; }
}

你想创建一个 WeakReference<MyOwnReference<WhatEver>> 吗?

我想知道是否可以在不改变JVM/环境的情况下实现这一点。

不,你可能无法“重新实现” WeakReference。它是由JVM支持的类。

你确定是创建 WeakReference 实例导致了性能变慢吗?我认为这样做不会导致性能问题。

ref = new WeakReference(someObject);

替代某些内容

ref.set(anotherObject);

那样会更加昂贵。


我正在实现某种迭代器。每当我前进到下一个条目时,我需要创建一个新的WeakReference。我进行了一些测试,似乎这会慢8-10倍。 - eold
我认为这个解决方案可能没有帮助。我刚刚运行了一个简单的基准测试,比较了创建强引用和弱引用的性能。结果强烈支持使用弱引用。这很奇怪但是可以重现,并且很可能是由于GC开销和强引用占用的不可回收内存造成的巨大开销。 - maaartinus

3
我正在实现某种迭代器。每次前进到下一个条目时,我需要创建一个新的WeakReference。在迭代器中使用WeakReference让人困惑。 WeakReference的常规用途是长期引用对象。但是,迭代器通常是短期对象,而迭代通常是短期过程。在短期内使用普通(强)引用来引用目标对象不应该成为问题。根据我的测试,似乎这样做会慢8-10倍。这再次表明您根本不应该使用WeakReference。您是否有特别的原因不能使用常规引用?

我想实现一个非故障快速的迭代器,当其引用的条目被删除时,该迭代器会立即变为无效。WeakReference提供了部分安全性,如果删除了该条目,则无法“取消引用”已删除的迭代器(该安全性仅是部分的,因为不能保证对象会立即被删除)。 - eold
你可以几乎确定,它不会立即被删除。此外,它可以从其他地方引用并且根本不会被删除。我不知道这样的迭代器应该提供什么优势。有时候快速失败是好的,有时候非失败(例如反映集合的某个旧状态)也是好的,但对于你的版本,我真的不知道。 - maaartinus
@leden - 我可以想到更好的(成本更低、更可靠)实现方式……这取决于你正在迭代的数据结构是什么。如果你提供了更多关于正在迭代的数据结构的细节,我可以给出更具体的建议。 - Stephen C
我正在迭代的东西最接近于一个链表。到目前为止,我想到的最好方法是为每个条目添加一个额外的布尔条目。这样,迭代器可以检查条目是否已删除。这会带来轻微的内存开销,如果存在可变弱引用,那么这种开销也会存在。你有更好的替代方案吗? - eold

0

你无法自己编写弱引用。它是JVM特殊处理的“特殊”类。

只需使用新的弱引用即可。

class MutableWeakReference<T> 

    WeakReference<T> wr;

    void set(T obj)
        wr = new WeakReference(obj);  

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