博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Guava Cache expireAfterWrite 与 refreshAfterWrite区别
阅读量:2443 次
发布时间:2019-05-10

本文共 3134 字,大约阅读时间需要 10 分钟。

前面的文章有讲到Guava Cache有区别于ConcurrentHashMap的使用,就是因为其自带有自动刷新和自动失效的功能,避免我们去自己编写刷新和失效的后台线程程序。Guava Cache提供了简单便捷的api给我们使用,但是研究源码发现这里的自动刷新缓存和自动失效原理,并非是Guava Cache帮我们去添加了类似后台线程自动刷新或失效逻辑的代码,而是用另外一种巧妙的方式进行。

expireAfterWrite 与 refreshAfterWrite区别

expireAfterWrite

在缓存更新后某个时间失效缓存,这里Guava内部会对某个时间点失效的缓存做统一失效,只要有get访问任一key,就会失效当前时间失效的缓存,会移除当前key。所以这里也希望我们创建的缓存数据量不宜过大,使用guavaCache最好是设置一下maximumSize,避免出现内存溢出的情况。失效后需要获取新值才可会返回。

refreshAfterWrite

是指在创建缓存后,如果经过一定时间没有更新或覆盖,则会在下一次获取该值的时候,会在后台异步去刷新缓存,如果新的缓存值还没有load到时,则会先返回旧值。这里跟上面的expireAfterWrite不同的是,及时到了该刷新的时间,不会失效旧值和移除对应key。在后台异步刷新的过程中,如果当前是刷新状态,及时有其他线程访问到旧值,依然只有一个线程在更新,不会出现多个线程同时刷新同一个key的缓存。

是否需要编写缓存刷新代码

不需要。上面讲到,使用了refreshAfterWrite后台会异步去刷新。这里后台刷新是使用线程池去完成异步刷新过程,即ListeningExecutorService sameThreadExecutor = MoreExecutors.sameThreadExecutor();

测试代码

这里是模拟1000个线程在3秒内10次从guavaCacha拿数据,通过loadTimes判断刷新了多少次,输出结果可以看到拿到的结果正确性。

代码已上传至

public class GuavaCacheRefreshTest {
@Data public class SkuCache {
private String skuId; private String skuCode; private Long realQuantity; } AtomicInteger loadTimes = new AtomicInteger(0); AtomicInteger count = new AtomicInteger(0); @Test public void testCacheUse() throws Exception {
LoadingCache
loadingCache = CacheBuilder.newBuilder() .refreshAfterWrite(1000, TimeUnit.MILLISECONDS) //Prevent data reloading from failing, but the value of memory remains the same .expireAfterWrite(1500, TimeUnit.MILLISECONDS) .build(new CacheLoader
() {
@Override public SkuCache load(String key) {
SkuCache skuCache = new SkuCache(); skuCache.setSkuCode(key + "---" + (loadTimes.incrementAndGet())); skuCache.setSkuId(key); skuCache.setRealQuantity(100L); System.out.println("load..." + key); return skuCache; } @Override public ListenableFuture
reload(String key, SkuCache oldValue) throws Exception {
checkNotNull(key); checkNotNull(oldValue); System.out.println("reload..."); //Simulate time consuming operation// Thread.sleep(1000); return Futures.immediateFuture(load(key)); } }); for (int i = 0; i < 1000; i++) {
new Thread(() -> {
try {
getValue(loadingCache); } catch (Exception e) {
e.printStackTrace(); } }).start(); } System.in.read(); System.out.println("finish"); } private void getValue(LoadingCache
loadingCache) throws Exception {
for (int i = 0; i < 10; i++) {
Thread.sleep(300l); System.out.println(loadingCache.get("sku").toString() + " - " + count.incrementAndGet()); } }}

转载地址:http://whnqb.baihongyu.com/

你可能感兴趣的文章
重新访问HHVM
查看>>
azure免费一个月_将Windows Azure提升到一个新的水平
查看>>
app engine 入门_Google App Engine和PHP:入门
查看>>
限流 php接口限流 代码_有效地使用PHP流
查看>>
使用Pspell查找和纠正拼写错误的单词
查看>>
PHP依赖注入容器性能基准
查看>>
gearman 任务失败_Gearman简介-PHP中的多任务
查看>>
成为PHP专业人员:缺少的链接
查看>>
了解OpCache
查看>>
symfony 2_使用Symfony 2:构建Web应用程序
查看>>
0xDBE:初步了解
查看>>
使用Phake自动化PHP-简介
查看>>
livereload_LiveReload
查看>>
vs2013项目迁移不成功_浏览器趋势2013年9月:迁移到Microsoft?
查看>>
如何在Windows上安装Ghost
查看>>
Magento电子商务网站的SEO指南
查看>>
用Mockery模拟您的测试依赖项
查看>>
Coderbits来自哪里?
查看>>
phpstorm -xmx_PhpStorm 8-新功能
查看>>
Chrome 27的新功能
查看>>