Как настроить кеш гуавы для удаления элемента после чтения?

Я хотел бы удалить (сделать недействительным) элемент после его чтения из кэша.

Таким образом, элемент должен присутствовать в кэше до первого чтения.

Я пытался добавить expireAfterAccess(0, TimeUnit.NANOSECONDS) но тогда кеш не заполняется.

Есть ли способ использовать кеш Guava таким образом, или мне нужно сделать недействительным элемент вручную после чтения?

3 ответа

Решение

Это не сработает. "Доступ" означает "доступ для чтения или записи", и когда он истекает сразу после чтения, то он также истекает сразу после записи.

Вы можете удалить запись вручную. Вы можете использовать asMap() просмотреть для того, чтобы сделать это в единый доступ:

String getAndClear(String key) {
    String[] result = {null};    
    cache.asMap().compute(key, (k, v) ->
        result[0] = v;
        return null;
    });
    return result[0];
}

Вы можете переключиться на Caffeine, который является более продвинутым кешем Guava и предлагает очень гибкий expireAfter(Expiry),

Однако я не думаю, что вам нужна работа для кеша. Поскольку одноразовые номера никогда не должны повторяться, я не могу представить себе причины хранить их. Обычно вы генерируете и используете их немедленно.

Возможно, вы делаете это неправильно, и вы можете захотеть уточнить, чтобы избежать возможных проблем с безопасностью.

В моем примере одноразовые номера создаются дважды:

LoadingCache<String, String> cache = CacheBuilder.newBuilder().expireAfterAccess(0, TimeUnit.NANOSECONDS)
    .build(new CacheLoader<String, String>() {
        @Override
        public String load(String key) throws Exception {
            return createNonce();
        }
    });

@Test
public void test_cache_eviction() throws Exception {
    String nonce1 = cache.getUnchecked("key");
    String nonce2 = cache.getUnchecked("key");
}

public String createNonce() {
    String createdNonce = "createdNonce";
    System.out.println(createdNonce);
    return createdNonce;
}

В логах "creatNonce" печатаются дважды.

Операция "получить и удалить" является простой remove на интерфейсе карты:

 Object cachedValue = cache.asMap().remove(key);
Другие вопросы по тегам