Я знаю, что есть файл WeakHashMap в java.util, но поскольку он использует WeakReferences для всего, на который ссылается только эта карта, ссылки на объекты теряются в следующем цикле GC. Таким образом, это почти бесполезно, если вы хотите кэшировать случайные данные, которые, скорее всего, будут запрошены снова, не будучи жестко связанными в остальное время. Лучшим решением будет карта, которая вместо этого использует SoftReferences, но я не нашел ее в пакете Java RT.
Есть ли SoftHashMap в Java?
Ответ 1
Изменить (август 2012):
Оказывается, в настоящее время лучшим решением, вероятно, являются классы Guava 13.0 Cache
, объясненные на Guava Wiki - что я собираюсь использовать.
Он даже поддерживает построение SoftHashMap
(см. CacheBuilder.newBuilder().softKeys()
), но это, вероятно, не то, что вы хотите, как объясняет эксперт Java Джереми Мэнсон (ниже вы найдете ссылку).
Не то, что Я знаю (ноябрь 2008 г.), но вы добрый находят некоторую реализацию SoftHashMap
в сети.
Как этот: SoftHashMap
или этот.
Изменить (ноябрь 2009 г.)
Как Matthias упоминается в комментариях, Google Guava MapMaker использует SoftReferences:
A
ConcurrentMap
, обеспечивающий любую комбинацию этих функций:
- мягкие или слабые клавиши,
- мягкие или слабые значения,
- время ожидания и
- вычисление значений по требованию.
Как упоминалось в этот поток, другой кандидат JSR166y:
jsr166y.ConcurrentReferenceHashMap
Он предоставляет альтернативную параллельную справочную карту для реализации Google (которая опирается на фоновый поток для высылки записей)
Изменить (август 2012)
Реализация Google использует фоновый поток только тогда, когда запрашивается время окончания ввода. В частности, он просто использует java.util.Timer
, который не настолько интрузивен, как имеющий отдельный фоновый поток.
Джереми Мэнсон рекомендует для любого кеша использовать эту функцию, чтобы избежать опасностей SoftReference: http://jeremymanson.blogspot.de/2009/07/how-hotspot-decides-to-clear_07.html
Существует еще одна реализация из Apache Commons, а именно org.apache.commons.collections.map.ReferenceMap; он не поддерживает временное удаление, но он поддерживает выбор того, должны ли ключи сравниваться по идентичности или по принципу равенства. Более того, эта реализация не является параллельной - ее можно синхронизировать, но она работает менее эффективно при доступе из нескольких потоков.
Ответ 2
Я знаком с двумя библиотеками, которые предлагают реализацию SoftHashMap:
-
Apache Commons: org.apache.commons.collections.map.ReferenceMap
-
Коллекции Google: com.google.common.collect.ReferenceMap
Ответ 3
Существует пример реализации в 98 выпуск бюллетеня java experts
Ответ 4
Считаете ли вы использование LRUMap вместо мягкой HashMap? Вы получаете больше контроля над тем, что хранится (или, по крайней мере, насколько).
Ответ 5
Apache Shiro поставляется с SoftHashMap, предназначенным для кэширования. Он основан на статье, опубликованной jb выше и лицензированной в Apache v2. Здесь вы можете найти документацию здесь и исходный код здесь.
Ответ 6
Если вы хотите реализовать кеш-ссылки, определенно лучше идея, чем слабые ссылки, но она ставит всю вашу политику удаления кеша в руки сборщика мусора. вероятно, не то, что вы хотите.
Если политика удаления кэша важна, вам нужно будет сделать это по своему усмотрению, используя регулярные ссылки. Однако вам нужно будет решить, когда вытаскивать предметы и которые нужно извлечь. Если вы только хотите потерять вещи, когда у вас заканчивается пустое пространство, вы можете запросить доступное пространство кучи с помощью:
Runtime.getRuntime().getFreeMemory();
Затем, когда свободная память опускается ниже определенной суммы, вы можете начать сбрасывать элементы. Или вы могли бы просто реализовать максимальный размер для кеша и использовать это, чтобы решить, когда бросать вещи.
here LRU cache, который я разработал с использованием O (1) вставки, удаления и времени поиска, который имеет настраиваемое максимальное количество элементов. Если вы хотите использовать кеш, это будет лучшее решение imho, чем SoftHashMap.
Смягчающие ссылки - отличный способ создать растущий кеш. Поэтому идеальным решением было бы использование SoftHashMap наряду с обычным кешем фиксированного размера. есть все вставки в кэш идет в обеих фиксированном кэш и мягкую хэш-карту, то ссылаться на что-то просто увидеть, если его в мягкой HashMap (и обновление отсчета времени в кэше). таким образом, все ваши самые важные элементы (в соответствии с выбранной вами политикой LRU, MFU,...) никогда не будут удалены, поскольку они жестко привязаны в кеше, но вы также будете придерживаться большего количества вещей (без какого-либо контроля политики) поскольку имеется достаточная память.