簡體   English   中英

清理與弱引用相關的資源

[英]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()的時間之間,另一個線程可以查詢引擎並仍然找到無效的引用。

我的問題是:如何在多線程上下文中保證引擎不會返回無效的引用?

您應該調整您的要求。 處理WeakReferenceList的代碼足夠低,足以處理WeakReferenceget()方法可能返回null的事實。 這段處理List代碼負責提供一個更高級別的API,該API既不顯示WeakReference也不顯示虛假的null值。 WeakHashMap類給出了這種設計的藍圖。 使用WeakHashMap的代碼不必處理可能的中間垃圾回收。 WeakHashMapget()方法在內部執行。

請注意,即使在收集和排隊之間沒有時間,也無法保證不會從get()方法中看到null值。 關鍵是要在另一個線程中進行清理,因此無論如何都無法保證計時。 隊列上的Reference並不意味着輪詢該隊列的清理線程會立即獲得CPU時間。 這將取決於系統的線程調度,您的清理線程是否在讀取List的線程獲得受影響的元素之前及時運行。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM