2012-04-17 54 views
3

我的問題值鍵關聯是:我怎樣才能一堆值的一串鑰匙如何無阻塞GC

  • 沒有直接修改鍵關聯,並
  • 不妨礙從得到GC'd鍵(明知值必須鍵強引用)

背景:

我需要用一些特定的對象(稱它們爲鍵)將一堆複雜的對象(稱之爲值)關聯起來。

通常情況下,我會這樣做的方式是使用關聯鍵和值的散列表。

This works great。但是,我還需要確保映射不會干擾密鑰的垃圾收集。換句話說,映射的存在不應該阻止密鑰被垃圾收集。

正常情況下,解決這個問題的方法是使用WeakHashMap,它只保存WeakReference的關鍵字。但是,WeakHashMaps只有在地圖中的值不具有對鍵的強引用時纔有效。不幸的是,我的值都強烈地引用了我的密鑰,這可以防止密鑰被垃圾收集。這可以通過對值使用弱引用來解決,但這不是一個可行的解決方案,因爲我不能讓我的值在我的密鑰之前GC'd。只要關鍵對象仍然存在,這些值也必須存在。

因此,我對這種情況的典型解決方案是停止使用HashMap,而是修改鍵以強有力地引用它所需的所有值。這將確保我仍然可以獲得給定密鑰的所有值,但不會阻止密鑰在自然生命週期完成時獲取GC'd。

不幸的是,我不能修改鍵,所以我不能直接將值添加到鍵。那麼還有什麼其他聰明的解決方案?

回答

2

給定的約束:

  • 鍵有一些排序的參考值
  • 的值必須鍵強引用
  • 不要阻止獲得GC的鑰匙」 d
  • 值不能鍵之前GC'd
  • 只要一個值項是否存在,這個值也必須存在
  • 值和鑰匙仍然應該GC-

......我不認爲這在邏輯上是可能的。

爲什麼不能刪除鍵值映射→(或至少使用引用不同但邏輯上爲.equal()的對象),然後使用WeakHashMap解決方案?

+0

,你的意思是刪除值的關鍵在於強大的參考?可悲的是,我無法修改這些值(或者說,我無法阻止用戶輸入對鍵有強烈參考的值,並且很有可能他們會這樣做) – emmby 2012-04-17 18:22:44

+0

是的,這就是我的意思。除非你爲鍵使用singleton/enum/flyweight模式類型,否則我仍然認爲你應該能夠在'WeakHashMap'中使用不同但在邏輯上相同的鍵來解決這個問題。 – 2012-04-17 18:24:42

+0

什麼將這些鍵保存在地圖中?他們不會在任意時間出現GC嗎? – emmby 2012-04-17 18:39:03

0

基本上解決你的問題是:
1.保持到鑰匙弱引用從你的價值觀,所以按鍵可以Gc'd
2.使用WeakHashMap中映射鍵的值(所以值不要GC'd,如果有強烈的參考鑰匙)。

下面是一個示例應用程序來解釋設計我上面提到的:通過「刪除值 - >鍵映射」

public class WeakApp { 

WeakHashMap<Key,Value> weakHashMap = new WeakHashMap<Key,Value>(); 
ArrayList <Key> strongReferences = new ArrayList<Key>(); 

static class Key { 
    String smthg = "key"; 
    public Key(int count) { 
     smthg = smthg + count; 
    } 

    public int hashCode() { 
     return smthg.hashCode(); 
    } 

    protected void finalize() { 
     System.out.println("Key object " + smthg + " Gc'd"); 
    } 
} 

static class Value { 

    static int count = 0; 
    WeakReference keyReference = null ; 
    String smthgValue = "Value object of key "; 

    public Value(Key key) { 
     keyReference = new WeakReference(key); 
     count++; 
     smthgValue = smthgValue + key.smthg; 

    } 
    protected void finalize() { 
     System.out.println(" " + smthgValue + " Gc'd"); 
    } 
} 

void initValueToKeys(){ 
    for(int i =0; i< 10; i ++) { 
     Key key = new Key(i); 
     strongReferences.add(key); 
     Value value = new Value(key); 
     weakHashMap.put(key, value); 
    } 
    System.out.println("Weak hash Map size is " + weakHashMap.size()); 
} 

void doMain() { 

    System.gc(); 
    System.runFinalization(); 

    //Now slowly remove the strong reference keys simulating them going out of use 
    Iterator<Key> itr = strongReferences.iterator(); 

    while(itr.hasNext()){ 
     Key key = itr.next(); 
     System.out.println("Removing strong reference to key " + key); 
     itr.remove(); 

    } 

    System.gc(); 
    System.runFinalization(); 

//shows if any values have references still from keys(should be 0), and expunges stale values to be Gc'd   
    System.out.println("Weak hash Map size is " + weakHashMap.size()); 

    //give chance for gc to remove the values 
    try { 
     Thread.sleep(1000); 
    } 
    catch(Exception e){ 
     e.printStackTrace(); 
    } 

    System.gc(); 
    System.runFinalization(); 

    System.out.println("System exited"); 
} 

public static void main(String[] args) { 
    WeakApp weakApp = new WeakApp(); 
    weakApp.initValueToKeys(); 
    weakApp.doMain(); 
} 

}

問候 奧斯汀