2012-04-17 2 views
3

Моего вопроса: Как я могу связать кучу значений с кучей ключейКак связать значения ключей без блокировки GC

  • без изменения ключей непосредственно, и
  • без предотвращая ключи от получения GC'd (зная, что значения имеют сильные ссылки на ключи)

фона:

Мне нужно связать кучу сложных объектов (вызывать их значения) несколькими частями (называть их ключами).

Как правило, так, как я делаю это, следует использовать хэш-карту, которая связывает ключи и значения.

Это прекрасно работает. Тем не менее, мне также необходимо убедиться, что сопоставления не мешают сбору мусора ключей. Другими словами, наличие сопоставления не должно препятствовать тому, чтобы ключ собирал мусор.

Обычно способ решения этой проблемы - использовать WeakHashMap, который содержит только ключи WeakReferences. Однако WeakHashMaps будет работать, только если значения на карте не имеют сильных ссылок на клавиши. К сожалению, мои ценности имеют сильные ссылки на мои ключи, что предотвращает сбор ключей от мусора. Это можно обойти, используя слабые ссылки на значения, но это не жизнеспособное решение, потому что я не могу допустить, чтобы мои значения были GC'd перед моими ключами. Пока ключевой объект все еще существует, значения также должны существовать.

Итак, мое типичное решение этой ситуации - прекратить использование HashMap и вместо этого изменить ключ, чтобы иметь сильные ссылки на все необходимые ему значения. Это гарантирует, что я все еще могу получить все значения для данного ключа, но не предотвратит получение ключа GC'd, когда будет выполнен естественный жизненный цикл.

К сожалению, я не могу изменить ключи, поэтому я не могу добавить значения непосредственно к клавишам. Итак, какие другие умные решения существуют?

ответ

2

Учитывая ограничения:

  • Клавиши имеют некоторые рода ссылки на значения
  • Значения имеют сильные ссылки на ключи
  • Не мешают ключи от получения GC» d
  • Значения не могут быть GC'd перед ключами
  • Пока существует ключ для значения, это значение должно также существовать
  • Значения и ключи должны по-прежнему быть GC -способными

... Я не думаю, что это логически возможно.

Почему вы не можете удалить значение → ключевых карт (или хотя бы использовать по-разному, но логически .equal() объектов), а затем пойти с решением WeakHashMap?

+0

на «удалить значение -> ключ отображения», вы имеете в виду удалить сильные ссылки, которые имеют значения на ключах? К сожалению, я не могу изменить значения (вернее, я не могу помешать пользователю вставлять значения, которые будут иметь сильные ссылки на ключи, и очень вероятно, что они это сделают) – emmby

+0

Да, это то, что я имею в виду , Если вы не используете шаблон типа singleton/enum/flyweight для ключей, я все же думаю, что вы должны иметь возможность использовать по-разному, но логически равные ключи в 'WeakHashMap' для решения этой проблемы. –

+0

Что бы сохранить эти ключи на карте? Разве они не получат GC'd в произвольное время? – emmby

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(); 
} 

}

Привет Остин

Смежные вопросы