2012-06-04 42 views
10

我想正確關閉可關閉的對象,當它不再被其他線程引用時。使用ReferenceQueue和WeakReference

我寫了一些小測試,但在對象入隊後,get方法返回null,即poll方法返回沒有指示對象的正確對象。

public static void main(String[] args) 
    { 
    ReferenceQueue<Closeable> reaped = new ReferenceQueue<Closeable>(); 
    Closeable s = <SOME CLOSEABLE IMPL>; 
    WeakReference<Closeable> ws = new WeakReference<Closeable>(s, reaped); 
    s = null; 

    System.gc(); 
    Closeable ro = (Closeable)reaped.poll().get(); 
    ro.close(); 
    } 

在此先感謝。 任何幫助將不勝感激。

回答

7

首先,如果只是關閉,請使用PhantomReference。 接下來,從參考隊列中,poll()不保證您將得到回參考。你永遠不會得到實際的物體(指稱物)。

如果你想確保你的Closeable已關閉,你必須自己跟蹤它們,可以在Map<Reference<?>, Closeable>中說。然後當你參考隊列poll()時,你最終會得到ref,那麼你必須使用它來從地圖上獲得Closeable

class MyThing { 
     Closeable c; 
    } 

    Map<Reference<MyThing>, Closeable> m = new HashMap(); 
    ReferenceQueue<MyThing> reaped = new ReferenceQueue<MyThing>(); 

    MyThing mt = new MyThing(); 
    mt.c = new MyClosable(); 

    Reference<MyThing> pref = new PhantomReference<MyThing>(mt, reaped); 
    m.put(pref, mt.c); 

    mt = null; 


    System.gc(); 
    Reference<MyThing> rf = reaped.poll(); 
    while (rf != null) { 
    m.get(rf).close(); 
    rf = reaped.poll(); 
    } 

如果你沒有真正的理由這樣做,或者如果你不明白什麼是你真的做,不要做這種事情。

您可以關閉您的文件中finally和BTW,如果它是關於文件,插座等,他們關閉了你(他們已經實現了finalize()

+0

嗨感謝這樣的快速反應,它是關於Lucene的的IndexSearcher的公司。 – yan

+0

我只是在System.gc()後面試過了,ReferenceQueue的大小爲0 – yan

+0

@yan不保證你的對象在System.gc()後不會得到GC,即使你退出JVM也是如此。不要使用finalization來處理業務邏輯,它只用於緩存和(最終)防止資源泄漏的特殊目的。你不能在終結器中說'commit()'或'rollback()'數據庫事務 –