LoadingCache缓存通过load和reload进行数据初始化和刷新。
load为同步加载数据,初始化时使用。
reload异步更新数据,更新数据时使用。
package thirdparty;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListenableFutureTask;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.common.util.concurrent.MoreExecutors;
import java.util.concurrent.*;
import java.util.logging.Logger;
import static common.constant.DigitalConstant.*;
import static common.constant.DigitalConstant.TWO;
/**
* LoadingCache测试样例.
*
* @author xindaqi
* @date 2021-07-18 13:41
*/
public class GuavaLoadingCacheTest {
private static final Logger logger = Logger.getLogger("GuavaLoadingCacheTest");
/**
* 普通线程池:ThreadPoolExecutor
*/
private static ExecutorService threadPoolExecutorGenerate = new ThreadPoolExecutor(
THREE,
FIVE,
THOUSAND_L,
TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>(TWO),
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.DiscardOldestPolicy());
/**
* Guava线程池
*/
private static ListeningExecutorService listeningExecutorService = MoreExecutors.listeningDecorator(threadPoolExecutorGenerate);
/**
* 建造LoadingCache,
* 使用ThreadPoolExecutor线程池异步刷新数据
*/
public static LoadingCache<String, String> loadingCache = CacheBuilder.newBuilder()
.refreshAfterWrite(10, TimeUnit.SECONDS)
.expireAfterWrite(11, TimeUnit.SECONDS)
.build(new CacheLoader<String, String>() {
@Override
public String load(String s) throws Exception {
return initializeCache();
}
@Override
public ListenableFuture<String> reload(String key, String oldValue)
throws Exception {
ListenableFutureTask<String> task = ListenableFutureTask
.create(GuavaLoadingCacheTest::reloadCache);
logger.info("==============Reload");
threadPoolExecutorGenerate.submit(task);
return task;
}
});
/**
* 建造LoadingCache,
* 使用Guava线程池异步刷新数据
*/
public static LoadingCache<String, String> loadingCacheAnother = CacheBuilder.newBuilder()
.refreshAfterWrite(10, TimeUnit.SECONDS)
.expireAfterWrite(11, TimeUnit.SECONDS)
.build(new CacheLoader<String, String>() {
@Override
public String load(String s) throws Exception {
return initializeCache();
}
@Override
public ListenableFuture<String> reload(String key, String oldValue)
throws Exception {
return listeningExecutorService.submit(GuavaLoadingCacheTest::reloadCache);
}
});
/**
* 初始化Cache.
*
* @return 默认值
*/
private static String initializeCache() {
loadingCache.put("1", "xiaohua");
loadingCache.put("2", "xiaolan");
loadingCache.put("3", "xiaoxiao");
logger.info("==========Load cache for initial==========");
return "xiaoxin";
}
/**
* 刷新Cache.
*
* @return 默认值
*/
private static String reloadCache() {
loadingCache.put("1", "xiaohuahua");
loadingCache.put("2", "xiaolanlan");
loadingCache.put("3", "xiaoxiaoxiao");
logger.info("==========Reload cache for refresh==========");
return "xiaoxinxin";
}
/**
* 读取Cache,通过load初始化
*/
private static void readCacheSelfInitialize() {
String val1 = loadingCache.getIfPresent("1");
logger.info("key1, value1:" + val1);
String val2 = loadingCache.getIfPresent("2");
logger.info("key2, value2:" + val2);
try {
String val1Get = loadingCache.get("1");
logger.info("val1:" + val1Get);
} catch(ExecutionException ee) {
throw new RuntimeException(ee);
}
}
/**
* 读取Cache,通过reload刷新数据
*/
private static void readCacheSelfRefreshTest() {
String val1 = loadingCache.getIfPresent("1");
logger.info("key1, value1:" + val1);
String val2 = loadingCache.getIfPresent("2");
logger.info("key2, value2:" + val2);
try {
String val1Get = loadingCache.get("1");
logger.info("val1:" + val1Get);
Thread.currentThread().sleep(2000);
} catch(ExecutionException ee) {
throw new RuntimeException(ee);
} catch(InterruptedException ie) {
throw new RuntimeException(ie);
}
}
public static void main(String[] args) {
readCacheSelfInitialize();
}
}
七月 18, 2021 2:37:17 下午 thirdparty.GuavaLoadingCacheTest readCacheSelfInitialize
信息: key1, value1:null
七月 18, 2021 2:37:18 下午 thirdparty.GuavaLoadingCacheTest readCacheSelfInitialize
信息: key2, value2:null
七月 18, 2021 2:37:18 下午 thirdparty.GuavaLoadingCacheTest initializeCache
信息: Load cache for initial
七月 18, 2021 2:37:18 下午 thirdparty.GuavaLoadingCacheTest readCacheSelfInitialize
信息: val1:xiaoxin
使用get方法获取LoadingCache数据时,没有获取到数据,调用load方法,load方法中可以初始化数据或者设置默认值。
public V get(K key) throws ExecutionException {
return this.localCache.getOrLoad(key);
}
V getOrLoad(K key) throws ExecutionException {
return this.get(key, this.defaultLoader);
}
使用getIfPresent方法,读取LoadingCache值:
(1)没有获取到值,LoadingCache返回null,通过判断返回值,进一步增加逻辑;
(2)获取到值,则直接使用。
@NullableDecl
public V getIfPresent(Object key) {
int hash = this.hash(Preconditions.checkNotNull(key));
V value = this.segmentFor(hash).get(key, hash);
if (value == null) {
this.globalStatsCounter.recordMisses(1);
} else {
this.globalStatsCounter.recordHits(1);
}
return value;
}
LoadingCache: