РЕДАКТИРОВАТЬ: Я реорганизовал этот вопрос, чтобы отразить новую информацию, которая с тех пор стала доступна.
Этот вопрос основан на ответах на вопрос Viliam относительно использования ленивым выселением на картах Гуавы: лени выселения на картах Гуавы
Пожалуйста, сначала прочтите этот вопрос и ответ на него, но по сути вывод: карты гуавы не асинхронно вычисляют и не приводят в исполнение выселение. Учитывая следующую карту:
ConcurrentMap<String, MyObject> cache = new MapMaker()
.expireAfterAccess(10, TimeUnit.MINUTES)
.makeMap();
После того, как прошло десять минут после доступа к записи, она все равно не будет выселена, пока карта не будет снова "затронута". Известные способы сделать это включают обычные средства доступа - get()
и put()
и containsKey()
.
Первая часть моего вопроса [решена]: какие еще вызовы вызывают «касание» карты? В частности, кто-нибудь знает, попадает ли size()
в эту категорию?
Причина удивления заключается в том, что я реализовал запланированную задачу, чтобы иногда подталкивать карту Гуавы, которую я использую для кэширования, используя этот простой метод:
public static void nudgeEviction() {
cache.containsKey("");
}
Однако я также использую cache.size()
, чтобы программно сообщать о количестве объектов, содержащихся на карте, как способ подтвердить, что эта стратегия работает. Но я не смог увидеть разницу с этими отчетами, и теперь мне интересно, если size()
также вызывает выселение.
Ответ: Итак, Марк указал, что в выпуске 9 выселение вызывается только методами get()
, put()
и replace()
, что объясняет, почему я не вижу эффект для containsKey()
. Очевидно, это изменится со следующей версией guava, которая скоро будет выпущена, но, к сожалению, релиз моего проекта установлен раньше.
Это ставит меня в интересное положение. Обычно я все еще могу дотронуться до карты, позвонив get("")
, но на самом деле я использую вычислительную карту:
ConcurrentMap<String, MyObject> cache = new MapMaker()
.expireAfterAccess(10, TimeUnit.MINUTES)
.makeComputingMap(loadFunction);
где loadFunction
загружает MyObject
, соответствующий ключу из базы данных. Похоже, у меня нет простого способа заставить выселиться до r10. Но даже способность надежно форсировать выселение ставится под сомнение второй частью моего вопроса:
Вторая часть моего вопроса [решена]: В ответ на один из ответов на связанный вопрос , надежно ли касание карты высвобождает все просроченные записи? В связанном ответе Niraj Tolia указывает на иное, говоря, что выселение потенциально может быть обработано только партиями, что может означать, что для того, чтобы все объекты с истекшим сроком действия были удалены, может потребоваться несколько вызовов для прикосновения к карте. Он не уточнил, однако это связано с тем, что карта разбита на сегменты в зависимости от уровня параллелизма. Предполагая, что я использовал r10, в котором containsKey("")
вызывает выселение, будет ли это тогда для всей карты или только для одного из сегментов?
Ответ: Мааартин обратился к этой части вопроса:
Помните, что containsKey
и другие методы чтения запускаются только postReadCleanup
, который ничего не делает, кроме каждого 64-го вызова (см. DRAIN_THRESHOLD). Более того, похоже, что все методы очистки работают только с одним сегментом.
Похоже, что вызов containsKey("")
не будет жизнеспособным решением даже в r10. Это сводит мой вопрос к названию: Как я могу надежно заставить выселение произойти?
Примечание: Одна из причин, по которой мое веб-приложение заметно затронуто этой проблемой, заключается в том, что когда я реализовал кэширование, я решил использовать несколько карт - по одной для каждого класса моих объектов данных. Таким образом, с этой проблемой существует вероятность того, что одна область кода будет выполнена, что приведет к кешированию группы объектов Foo
, и затем кэш Foo
не будет снова затронут в течение длительного времени, поэтому он не будет освобожден что-нибудь. Между тем объекты Bar
и Baz
кэшируются из других областей кода, а память используется. Я устанавливаю максимальный размер на этих картах, но в лучшем случае это хрупкая гарантия (я предполагаю, что ее эффект незамедлительный - все еще нужно это подтвердить).
ОБНОВЛЕНИЕ 1: Спасибо Даррену за ссылку на соответствующие вопросы - теперь у них есть мои голоса. Таким образом, похоже, что разрешение находится в стадии разработки, но вряд ли будет в r10. Пока что мой вопрос остается.
ОБНОВЛЕНИЕ 2: На данный момент я просто жду от члена команды Гуавы, чтобы дать отзыв о взломе maaartinus, и я собрал (см. Ответы ниже).
ПОСЛЕДНИЕ ОБНОВЛЕНИЯ: отзыв получен!