Потенциальное использование для SoftReference с равным значением (равно) - PullRequest
9 голосов
/ 12 февраля 2010

Ранее я пришел к выводу, что если вам нужна SoftReference с равенством, основанным на значении (равно), то у вас был плохой дизайн, за исключением интернера. Это следует за Google Collections и Guava, не включая такой класс. Но я столкнулся с проблемой, которая, я думаю, могла бы использовать такой объект.

У нас есть система управления активами в ферме визуализации эффектов с сотнями процессов, выполняющих одно и то же задание, которые отличаются только номером кадра, который он отображает. У нас есть база данных Oracle, которая должна записывать все используемые активы. Вместо того, чтобы использовать Oracle с одинаковыми вставками, где только одна будет выполнять все задания, в системе управления активами среднего уровня мы можем использовать HashSet для записи, будет ли объект, который будет вставлен в Oracle.

Я мог бы использовать Google MapMaker с истечением срока действия, но я не хочу беспокоиться о том, чтобы получить правильное окончание срока действия, у нас есть рендеры, которые выполняются за часы, а некоторые за несколько дней. Использование SoftReference с равным равенством звучит намного лучше, так что JVM будет автоматически управлять сборкой мусора.

Для других проблем, которые я хочу решить с помощью ConcurrentHashMap со сборкой мусора, я бы использовал сильную ссылку в HashMap в качестве ключа для получения равенства equals () и SoftReference в качестве значения, чтобы JVM могла что-то собирать, но в этом случае значение не имеет значения, и у меня нет значения для переноса в SoftReference для помещения туда. Таким образом, кажется, что использование SoftReference с equals () поможет.

Любые другие предложения по этому поводу?

Ответы [ 3 ]

1 голос
/ 23 февраля 2010

Поскольку нет ConcurrentHashSet с использованием мягких ссылок, есть только два подхода:

1.) Ваш подход с ConcurrentHashMap

  • Переопределить equals и hashCode в SoftReference
  • Внутри equals и hashCode доступ к объекту возможен только с использованием SoftReference#get
  • Введите SoftReference в качестве ключа и любой объект в качестве значения (только ноль не допускается)
  • Если ссылка становится устаревшей при доступе к hashCode или равно, добавьте ссылку в очередь удаления, чтобы часто удалять мертвые ключи.
  • Проверить наличие через containsKey

2.) Используйте ConcurrentMultimap<Integer, Set<SoftReference<RepLookupEntry>> и используйте hashCode в качестве ключа, а синхронизированный набор SoftReferences в качестве значений. Когда вы получаете удар hashCode, проверьте содержимое всех SoftReferences на равенство. Не очень красиво, я согласен и сложно синхронизировать.

Если бы я был на вашем месте, я бы вообще не использовал SoftReferences, а скорее ConcurrentHashMap для сохранения сильных ссылок на ваши POJO. Каждый раз, когда приходит новый элемент, также помещайте его в ConcurrentLinkQueue. Если очередь превышает определенный предел, начните удалять элементы из HashMap.

1 голос
/ 15 февраля 2010

В большинстве случаев, когда вы хотите использовать мягкие ссылки с Google Collections, вам следует позвонить

MapMaker.softValues()

При наличии сильных клавиш, но мягких значений при поиске будет использоваться равенство, а пары ключ-значение будут собираться мусором при нехватке памяти.

0 голосов
/ 17 февраля 2010

Я думаю, что этот класс будет соответствовать вашим потребностям:

import java.util.*;
import java.lang.ref.*;

public class SoftSet<T> extends AbstractSet<T> {

  private final WeakHashMap<T,SoftReference<T>> data = new WeakHashMap<T,SoftReference<T>>();

  public boolean add(T t) {
    return null == data.put(t, new SoftReference<T>(t));
  }

  public boolean remove(Object o) {
    return null != data.remove(o);
  }

  public boolean contains(Object o) {
    return data.containsKey(o);
  }

  public Iterator<T> iterator() {
    return data.keySet().iterator();
  }

  public int size() {
    return data.size();
  }

  public void clear() {
    data.clear();
  }

  public boolean removeAll(Collection<?> c) {
    return data.keySet().removeAll(c);
  }

  public boolean retainAll(Collection<?> c) {
    return data.keySet().retainAll(c);
  }
}

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

...