Лень выселения на картах Гуавы

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

Например, сопоставление адресов с индексаторами определяется как:

ConcurrentMap<Address, Indexer> indexers = new MapMaker()
  .expireAfterAccess( EXPIRATION, TimeUnit.SECONDS)
  .evictionListener( new IndexEvicted())
  .makeMap();

приводит к довольно удивительной закономерности: пока containsKey() для данного адреса возвращается false, сразу после того, как индексатор для этого адреса будет удален.

Каков был бы рекомендуемый подход, чтобы сделать процесс очистки более оперативным? Т.е. убрать объекты, близкие к фактическому времени истечения.

Обновление: я хотел бы уточнить, что я имею в виду в режиме реального времени. Для приведенного выше примера, EXPIRATION составляет 10 секунд, я бы хотел, чтобы вставленный объект выселился через 10 секунд после последнего доступа. Этого сейчас не происходит - карту нужно использовать как-то, чтобы начать выселение. Если карта полностью не используется, объект может оставаться там годами.

3 ответа

Решение

Для своевременного выселения в Guava потребуется реализовать какой-то фоновый поток или выполнить повторяющуюся по времени задачу. Это сделало бы карту более тяжелой и трудной для использования в таких средах, как J2EE или в средах, где политика безопасности не позволяет потокам порождаться волей-неволей.

Если вы заботитесь о своевременном выселении, создайте собственную временную ветку, которая касается карты.

С другой стороны, я согласен с тем, что иметь выселение, запускаемое сборщиком мусора, было бы неплохо... например, с помощью SoftReference и финализатора. (Да, я знаю, что финализаторы в основном злые, я просто предлагаю дополнительную стратегию последней инстанции.)

Есть expireAfterWrite метод в дополнение к expireAfterAccess, Это, вероятно, отвечает всем требованиям.

Из Javadoc:

Указывает, что каждая запись должна автоматически удаляться с карты по истечении фиксированной продолжительности с момента создания или замены записи. Обратите внимание, что изменение значения записи сбрасывает время ее истечения.

Примечание: оба expireAfterAccess а также expireAfterWrite "в реальном времени", просто один истекает элементы на основе их последнего времени записи, а другой на основе их последнего времени доступа.

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

Другие вопросы по тегам