Когда бы вы использовали WeakHashMap или WeakReference? - PullRequest
156 голосов
/ 01 октября 2008

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

Ответы [ 10 ]

94 голосов
/ 01 октября 2008

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

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

Понимание слабых ссылок , Итан Николас

52 голосов
/ 01 октября 2008

Одно из различий, которое необходимо прояснить, - это разница между WeakReference и SoftReference.

Обычно WeakReference будет GC-d JVM с нетерпением, как только у объекта, на который имеется ссылка, нет жестких ссылок на него. Объект SoftReference d, с другой стороны, будет собираться сборщиком мусора до тех пор, пока ему действительно не понадобится освободить память.

Кэш, в котором значения содержатся внутри WeakReference s, будет довольно бесполезным (в WeakHashMap это ключи, на которые слабо ссылаются). SoftReferences полезны для переноса значений, когда вы хотите реализовать кеш, который может увеличиваться и уменьшаться с доступной памятью

29 голосов
/ 15 октября 2008

Один Общее использование WeakReference с и WeakHashMap с, в частности, для добавления свойств к объектам. Иногда вы хотите добавить некоторую функциональность или данные к объекту, но подклассы и / или композиция не являются вариантом в этом случае, очевидная вещь, которую нужно сделать, это создать хэш-карту, связывающую объект, который вы хотите расширить, со свойством, которое вы хотите добавить , тогда, когда вам нужно это свойство, вы можете просто посмотреть его на карте. Однако, если объекты, которые вы добавляете в свои свойства, как правило, разрушаются и создаются много, вы можете получить много старых объектов на вашей карте, занимающих много памяти.

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

Мне нужно было сделать это, чтобы добавить некоторые данные в java.awt.Component, чтобы обойти изменения в JRE между 1.4.2 и 1.5, я мог бы исправить это, создав подклассы для каждого интересующего меня компонента int (JButton, JFrame, JPanel ....) но это было намного проще с гораздо меньшим количеством кода.

19 голосов
/ 11 августа 2014

Другим полезным случаем для WeakHashMap и WeakReference является реализация реестра прослушивателей .

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

manager.registerListener(myListenerImpl);

Если manager хранит ваш слушатель с WeakReference, это означает, что вам не нужно удалять регистр, например. с manager.removeListener(myListenerImpl), поскольку он будет автоматически удален, как только ваш слушатель или ваш компонент, удерживающий слушателя, станет недоступным.

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

Откуда WeakHashMap входит в картину?

Реестру слушателей, который хочет хранить зарегистрированных слушателей как WeakReference s, нужна коллекция для хранения этих ссылок. В стандартной библиотеке Java нет реализации WeakHashSet, кроме WeakHashMap, но мы можем легко использовать последнюю для «реализации» функциональности первой:

Set<ListenerType> listenerSet =
    Collections.newSetFromMap(new WeakHashMap<ListenerType, Boolean>());

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

4 голосов
/ 01 октября 2008

Этот пост блога демонстрирует использование обоих классов: Java: синхронизация по идентификатору . Использование идет примерно так:

private static IdMutexProvider MUTEX_PROVIDER = new IdMutexProvider();

public void performTask(String resourceId) {
    IdMutexProvider.Mutex mutext = MUTEX_PROVIDER.getMutex(resourceId);
    synchronized (mutext) {
        // look up the resource and do something with it
    }
}

IdMutextProvider предоставляет объекты на основе идентификатора для синхронизации. Требования:

  • должен возвращать ссылку на тот же объект для одновременного использования эквивалентных идентификаторов
  • должен возвращать другой объект для разных идентификаторов
  • нет механизма освобождения (объекты не возвращаются провайдеру)
  • не должно протекать (неиспользуемые объекты могут собираться мусором)

Это достигается с помощью внутренней карты хранения типа:

WeakHashMap<Mutex, WeakReference<Mutex>>

Объект является и ключом, и значением. Когда ничто внешнее к карте не имеет жесткой ссылки на объект, это может быть сбор мусора. Значения на карте хранятся с жесткими ссылками, поэтому значение должно быть заключено в WeakReference для предотвращения утечки памяти. Этот последний пункт описан в javadoc .

3 голосов
/ 01 октября 2008

Как указано выше, слабая ссылка сохраняется до тех пор, пока существует сильная ссылка.

Примером использования было бы использование WeakReference внутри слушателей, чтобы слушатели перестали быть активными после того, как основная ссылка на их целевой объект исчезла. Обратите внимание, что это не означает, что WeakReference удален из списка слушателей, очистка все еще требуется, но может быть выполнена, например, в запланированное время. Это также препятствует тому, чтобы прослушиваемый объект удерживал сильные ссылки и в конечном итоге становился источником раздувания памяти. Пример: компоненты Swing GUI, ссылающиеся на модель с более длинным жизненным циклом, чем у окна.

Играя со слушателями, как описано выше, мы быстро поняли, что объекты собираются "немедленно" с точки зрения пользователя.

3 голосов
/ 01 октября 2008

Если вы, например, хотите отслеживать все объекты, созданные определенного класса. Чтобы по-прежнему разрешать сборку этих объектов, вы храните список / карту слабых ссылок на объекты вместо самих объектов.

Теперь, если бы кто-то мог объяснить мне призрачные ссылки, я был бы счастлив ...

2 голосов
/ 01 октября 2008

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

1 голос
/ 01 октября 2008

Я выполнил поиск в Google-коде по запросу "new WeakHashMap ()".

Я получил кучу совпадений из проекта GNU classpath и

  1. Apache xbean Проект: WeakHashMapEditor.java
  2. Проект Apache Lucene: CachingWrapperFilter.java
0 голосов
/ 01 октября 2008

вы можете использовать weakhashmap для реализации бесресурсного кэширования для создания обширного объекта.

но учтите, что нежелательно иметь изменяемые объекты. я использовал его для кэширования результатов запроса (выполнение которых занимает около 400 мс) в механизм текстового поиска, который редко обновляется.

...