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
Cachebuilt with an attachedCacheLoader. (…) The canonical way to query aLoadingCacheis with the methodget(K). This will either return an already cached value, or else use the cache’sCacheLoaderto 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");