[英]Cleaning up resources associated with weak reference
在一個程序中,我需要將弱引用存儲在某個存儲引擎(實際上是嵌入式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
中獲取回收的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()
的時間之間,另一個線程可以查詢引擎並仍然找到無效的引用。
我的問題是:如何在多線程上下文中保證引擎不會返回無效的引用?
您應該調整您的要求。 處理WeakReference
的List
的代碼足夠低,足以處理WeakReference
的get()
方法可能返回null
的事實。 這段處理List
代碼負責提供一個更高級別的API,該API既不顯示WeakReference
也不顯示虛假的null
值。 WeakHashMap
類給出了這種設計的藍圖。 使用WeakHashMap
的代碼不必處理可能的中間垃圾回收。 WeakHashMap
的get()
方法在內部執行。
請注意,即使在收集和排隊之間沒有時間,也無法保證不會從get()
方法中看到null
值。 關鍵是要在另一個線程中進行清理,因此無論如何都無法保證計時。 隊列上的Reference
並不意味着輪詢該隊列的清理線程會立即獲得CPU時間。 這將取決於系統的線程調度,您的清理線程是否在讀取List
的線程獲得受影響的元素之前及時運行。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.