2014-02-07 37 views
0

在一个程序中,我需要将弱引用存储在某个存储引擎(实际上是嵌入式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();  
    } 
    ... 
} 

下面的代码显示的参考文献中是如何

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) {} 
      } 
    } 
} 

虽然在我的测试中,这是工作的罚款,我发现了以下工作:在一个单独的线程从ReferenceQueue需要回收的引用,并调用其cleanUp()方法清洗所述WeakReference类的文档中:

假设垃圾回收器确定在 时间,一个对象是弱可某一点。那时它会原子上清除对该对象的所有弱引用......在相同的 时间或稍后的时间它将排入那些新引用的弱 引用,这些引用是用引用队列注册的。

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

我的问题是:我怎么能保证在多线程的上下文中,失效的引用永远不会被我的引擎返回?

+0

简短的回答,你不能。您需要更改您的要求或使用其他设施。 – jtahlborn

+0

如果您想要提供替代解决方案的建议,则必须提供有关您尝试解决的问题的更多详细信息。 – jtahlborn

+0

hi @jtahlborn通过使用“另一个设施”,你的意思是什么? – Sergio

回答

0

您应该调整您的要求。处理WeakReferenceList的代码很低,足以处理WeakReference的方法可能返回null这一事实。此代码涉及List负责提供更高级别的API,既不显示WeakReference也不显示虚假null值。类WeakHashMap给出了这样的设计蓝图。使用WeakHashMap的代码不必处理可能的垃圾收集。 WeakHashMapget()方法在内部进行。

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