【问题标题】:Cleaning up resources associated with weak reference清理与弱引用相关的资源
【发布时间】:2014-02-07 16:07:56
【问题描述】:

在一个程序中,我需要将弱引用存储在某个存储引擎(实际上是嵌入式 Prolog 数据库)中。为了使解释简单,可以将这种存储引擎(在本问题的上下文中)视为弱引用的集合。

我需要保证,一旦引用被回收,弱引用就会从存储引擎中收回。换句话说,如果 get() 方法已经返回 null,则应该无法从引擎访问弱引用。

我目前通过ReferenceQueue 实现了这一点。

以下代码通过添加cleanUp() 方法(调用从引擎中删除弱引用的清理任务)来扩展弱引用:

public class MyWeakRef<REF_TYPE> extends WeakReference<REF_TYPE> {

    MyWeakRef(REF_TYPE referent, ReferenceQueue<REF_TYPE> referenceQueue, Runnable cleaningTask, ...) {
        super(referent, referenceQueue);
        this.cleaningTask = cleaningTask;
        ...
    }

    void cleanUp() {
        cleaningTask.run();     
    }
    ...
}

下面的代码显示了如何在一个单独的线程中清理引用,该线程从 ReferenceQueue 获取回收的引用并调用它们的 cleanUp() 方法:

public class WeakReferencesCleaner extends Thread {

    private static WeakReferencesCleaner referencesCleaner = new WeakReferencesCleaner(new ReferenceQueue<Object>());

    public static WeakReferencesCleaner getWeakReferencesCleaner() {
        return referencesCleaner;
    }

    public synchronized static void startWeakReferencesCleaner() {
        if(!referencesCleaner.isAlive())
            referencesCleaner.start();
}

    private ReferenceQueue<?> referenceQueue;

    public WeakReferencesCleaner(ReferenceQueue<?> referenceQueue, int priority) {
        this.referenceQueue = referenceQueue;
        this.setDaemon(true);
    }

    public ReferenceQueue<?> getReferenceQueue() {
        return referenceQueue;
    }

    @Override
    public void run() {
        while(true) {
            try {
                MyWeakRef<?> ref = (JTermRef<?>) referenceQueue.remove();
                try {
                    ref.cleanUp();
                } catch(Exception e) {
        ...
            }
                } catch (InterruptedException e) {}
            }
    }
}

虽然在我的测试中这工作正常,但我在 WeakReference 类的文档中发现了以下内容:

假设垃圾收集器在某个时间点确定 对象弱可达的时间。到时候就会 原子地清除对该对象的所有弱引用......同时 时间或稍后的某个时间,它会将那些新清除的弱者排入队列 在引用队列中注册的引用。

因此,在引用失效和方法cleanUp() 执行之间,另一个线程可以查询引擎并仍然找到失效的引用。

我的问题是:如何在多线程上下文中保证我的引擎永远不会返回无效的引用?

【问题讨论】:

  • 简短回答,你不能。您需要更改您的要求或使用其他设施。
  • 如果您需要替代解决方案的建议,您必须提供有关您尝试解决的问题的更多详细信息。
  • 嗨 @jtahlborn 你所说的使用“另一个设施”是什么意思?
  • @jtahlborn 我要解决的问题是实现嵌入在 Java 中的 Prolog 引擎,支持存储和操作(弱)引用。
  • “存储”是什么意思,弱引用指的是什么? prolog 引擎与任何事物有什么关系?

标签: java multithreading garbage-collection weak-references


【解决方案1】:

您应该调整您的要求。处理WeakReferences 的List 的代码级别足够低,足以处理WeakReferenceget() 方法可能返回null 的事实。处理List 的这段代码负责提供更高级别的API,它既不显示WeakReferences 也不显示虚假的null 值。 WeakHashMap 类给出了这种设计的蓝图。使用WeakHashMap 的代码不必处理可能的中间垃圾收集。 WeakHashMapget() 方法在内部执行。

请注意,即使在收集和排队之间没有时间,也不能保证不会从 get() 方法中看到 null 值。关键是您正在另一个线程中进行清理,因此无论如何都不能保证时间。队列中的Reference 并不意味着轮询该队列的清理线程立即获得 CPU 时间。在读取List的线程获取受影响的元素之前,您的清理线程是否及时运行取决于系统的线程调度。

【讨论】:

    猜你喜欢
    • 2010-10-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多