Когда вы будете использовать WeakHashMap или WeakReference?

StackOverflow https://stackoverflow.com/questions/154724

  •  03-07-2019
  •  | 
  •  

Вопрос

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

Это было полезно?

Решение

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

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

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

Другие советы

Единственное различие, которое следует прояснить, — это разница между WeakReference и SoftReference.

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

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

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

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

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

Еще один полезный случай для WeakHashMap и WeakReference это реализация реестра прослушивателей.

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

manager.registerListener(myListenerImpl);

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

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

Где же WeakHashMap войти в картину?

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

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

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

В этом сообщении блога показано использование обоих классов: Джава:синхронизация по идентификатору.Использование происходит примерно так:

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>>

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

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

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

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

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

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

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

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

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

  1. Проект Apache xbean: WeakHashMapEditor.java
  2. Проект Apache Lucene: КэшированиеWrapperFilter.java

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top