I have a cache of String, Boolean.:
Cache<String, Boolean> myCache = CacheBuilder.newBuilder().build();
My usage pattern is:
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 }
I am trying to change this so that it uses the alternative get
method that takes a loader function get(K key, Callable<? extends V> loader)
, to avoid the possibility that two threads both call myCache.get("some-key") == null
and both enter the if block.
I am not sure if below is the correct way to do this?
I think myCache.get("some-key", myCacheLoader)
will insert some-key
into the cache if it is not present, but I also need to know if it was present or not, so I don’t think the code below is correct.
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 }
Advertisement
Answer
Build LoadingCache
instead of Cache
with the CacheLoader
to achieve what you want. Please refer to Guava CachesExplained wiki page, specifically:
A LoadingCache is a
Cache
built with an attachedCacheLoader
. (…) The canonical way to query aLoadingCache
is with the methodget(K)
. This will either return an already cached value, or else use the cache’sCacheLoader
to atomically load a new value into the cache.
In your case:
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");