Guava CacheBuilder не вызывает прослушиватель удаления
Я хочу: получать уведомление, когда сущность удаляется с истечением срока ожидания.
Я попробовал: Установить прослушиватель удаления.
Проблема: Похоже, что прослушиватель удаления не работает правильно. Он работает только тогда, когда я помещаю новые элементы в кеш (см. Код ниже)
Вопрос: Как сделать работу прослушивателя удаления без добавления новых элементов?
Код:
Мой кэш загрузки:
LoadingCache<String, Integer> ints = CacheBuilder.newBuilder()
.maximumSize(10000)
.expireAfterAccess(ACCESS_TIMEOUT, TimeUnit.MILLISECONDS)
.removalListener(
new RemovalListener() {
//PROBLEM: THIS METHOD IS NEVER CALLED!!!
public void onRemoval(RemovalNotification notification) {
if (notification.getCause() == RemovalCause.EXPIRED) {
System.out.println("Value " + notification.getValue() + " has been expired");
} else {
System.out.println("Just removed for some reason");
}
}
}
)
.build(
new CacheLoader<String, Integer>() {
public Integer load(String key) throws Exception {
return new Integer(-1);
}
});
как я использую кеш в отдельном потоке:
cache.put("key", 100);
Thread.sleep(ACCESS_TIMEOUT / 2);
System.out.println(cache.getIfPresent(key)); //returns 100
Thread.sleep(ACCESS_TIMEOUT * 5);
//CRUCIAL STRING: cache.put("key2", 200); //invoke removal listener
System.out.println(cache.getIfPresent(key)); //return null
//And again: the problem is that entity has been already expired, but removal listener isn't called untill I add new item to the cache.
P.S: Я могу поделиться полной демонстрацией в GitHub, если вам нужно, просто скажите мне
Ответы
Ответ 1
Это потому, что Guava не гарантирует выселения значений автоматически, когда истекает время ожидания. Однако это происходит во время серии операций чтения и записи.
В документации здесь:
Кэши, созданные с помощью CacheBuilder, не выполняют значения очистки и выселения "автоматически" или сразу после истечения срока действия или что-либо из вид. Вместо этого он выполняет небольшие объемы обслуживания во время операций записи или во время периодических операций чтения, если записи редко.
Причиной этого является следующее: если мы хотим выполнить кеш нам нужно было бы создать поток, а его операции будут конкурировать с пользовательскими операциями для общих блокировок. Кроме того, некоторые среды ограничивают создание потоков, что делает CacheBuilder непригодным для использования в этой среде.
Чтобы проверить ваш onRemoval
по истечении срока действия, вызовите cache#cleanUp
непосредственно перед вашей второй операцией чтения, и она должна вызвать ваш onRemoval
.