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.