Правильное использование для использования загрузочного кэша с ?

#java #guava

#java #гуава

Вопрос:

У меня есть кэш String, Boolean .:

 Cache<String, Boolean> myCache = CacheBuilder.newBuilder().build();
  

Мой шаблон использования:

 if (myCache.get("some-key") == null)  {
     // "some-key" not in cache, do stuff, then insert it
     myCache.put("some-key", Boolean.TRUE);
} 
else {
    // "some-key" already in cache
}
  

Я пытаюсь изменить это так, чтобы он использовал альтернативный get метод, который принимает функцию загрузчика get(K key, Callable<? extends V> loader) , чтобы избежать возможности того, что два потока одновременно вызывают myCache.get("some-key") == null и оба вводят блок if .

Я не уверен, что ниже приведен правильный способ сделать это?

Я думаю myCache.get("some-key", myCacheLoader) , что он будет вставлен some-key в кэш, если его нет, но мне также нужно знать, присутствовал он или нет, поэтому я не думаю, что приведенный ниже код правильный.

 CacheLoader<String, Boolean> myCacheLoader = createMyCacheLoader();
Cache<String, Boolean> myCache = CacheBuilder.newBuilder().build();

private static CacheLoader<String, Boolean> createMyCacheLoader(){
    return new CacheLoader<String, Boolean>(){
        @Override
        public Boolean load(final String key){
            return Boolean.TRUE;
        }
    };
}

if (!myCache.get("some-key", myCacheLoader))  { // I don't think this can ever be false?
    // I don't think if block will ever be entered?
    // How can I find out if an item isn't in the cache when using a loading cache?
} 
else {
    // "some-key" already in cache 
}
  

Комментарии:

1. Взгляните на build перегрузку метода, которая принимает CacheLoader .

Ответ №1:

Создайте LoadingCache вместо Cache с CacheLoader , чтобы достичь того, чего вы хотите. Пожалуйста, обратитесь к вики-странице Guava CachesExplained, в частности:

LoadingCache — это Cache встроенный с подключенным CacheLoader . (…) Канонический способ запроса a LoadingCache — это метод get(K) . Это либо вернет уже кэшированное значение, либо будет использовать кэш CacheLoader для атомной загрузки нового значения в кэш.

В вашем случае:

     CacheLoader<String, Boolean> myCacheLoader = CacheLoader.from(key -> Boolean.TRUE);
    LoadingCache<String, Boolean> myCache = CacheBuilder.newBuilder()
            // optional config for LoadingCache
            .build(myCacheLoader);

    // or even inlined:
    LoadingCache<String, Boolean> myCache = CacheBuilder.newBuilder()
            // optional config for LoadingCache
            .build(CacheLoader.from(key -> Boolean.TRUE));

    try {
        final Boolean isValuePresent = myCache.get("some-key");
    } catch (ExecutionException e) {
        throw new UncheckedExecutionException(e.getCause()); // or whatever
    }

    final Boolean isAnotherValuePresent = myCache.getUnchecked("some-key-as-well");