Google Guava之--cache
一、简介
Google Guava包含了Google的Java项目许多依赖的库,如:集合 [collections] 、缓存 [caching] 、原生类型支持 [primitives support] 、并发库 [concurrency libraries] 、通用注解 [common annotations] 、字符串处理 [string processing] 、I/O 等等。本文只介绍其中的缓存部分。
Guava Cache是一种本地缓存实现,支持多种缓存过期策略。性能好,简单易用。缓存在很多场景下都是很有用的。如,通过key获取一个value的花费的时间很多,而且获取的次数不止一次的时候,就应该考虑使用缓存。Guava Cache与ConcurrentMap很相似,但也不完全一样。最基本的区别是ConcurrentMap会一直保存所有添加的元素,直到显式地移除。而Guava Cache为了限制内存占用,通常都设定为自动回收元素。在某些场景下,尽管LoadingCache 不回收元素,它也会自动加载缓存。
Guava Cache适用于以下应用场景:
- 系统的访问速度首要考虑,而内存空间为次要考虑。
- 某些key对于的value会被查询多次。
- 缓存中存放的数据总量不会超出内存的全部大小。
本文例子使用的guava 版本为guava-18.0.jar,下载地址如下:
http://central.maven.org/maven2/com/google/guava/guava/18.0/guava-18.0.jar
二、Cache使用方式
1、CacheLoader方式
代码如下:
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit; import org.junit.Test; import com.google.cacahe.Person;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache; public class TestGuavaCache { @Test
public void testUserCacheLoader() throws ExecutionException {
// 模拟数据
final List<Person> list = new ArrayList<Person>(5);
list.add(new Person("1", "zhangsan"));
list.add(new Person("2", "lisi"));
list.add(new Person("3", "wangwu")); // 创建cache
LoadingCache<String, Person> cache = CacheBuilder.newBuilder()//
.refreshAfterWrite(1, TimeUnit.MINUTES)// 给定时间内没有被读/写访问,则回收。
// .expireAfterWrite(5, TimeUnit.SECONDS)//给定时间内没有写访问,则回收。
// .expireAfterAccess(3, TimeUnit.SECONDS)// 缓存过期时间为3秒
.maximumSize(100).// 设置缓存个数
build(new CacheLoader<String, Person>() {
@Override
/** 当本地缓存命没有中时,调用load方法获取结果并将结果缓存
*/
public Person load(String key) throws ExecutionException {
System.out.println(key + " load in cache");
return getPerson(key);
} // 此时一般我们会进行相关处理,如到数据库去查询
private Person getPerson(String key) throws ExecutionException {
System.out.println(key + " query");
for (Person p : list) {
if (p.getId().equals(key))
return p;
}
return null;
}
}); cache.get("1");
cache.get("2");
cache.get("3");
System.out.println("======= sencond time ==========");
cache.get("1");
cache.get("2");
cache.get("3");
}
}
执行结果如下:
1 load in cache
1 query
2 load in cache
2 query
3 load in cache
3 query
======= sencond time ==========
第二次获取的时候没有执行获取的方法,而是直接从缓存中获取。
2、Callback方式
代码如下:
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException; import org.junit.Test; import com.google.cacahe.Person;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder; public class TestGuavaCache { @Test
public void testUserCallback() throws ExecutionException {
// 模拟数据
final List<Person> list = new ArrayList<Person>(5);
list.add(new Person("1", "zhangsan"));
list.add(new Person("2", "lisi"));
list.add(new Person("3", "wangwu")); final String key = "1";
Cache<String, Person> cache2 = CacheBuilder.newBuilder().maximumSize(1000).build();
/**
* 用缓存中的get方法,当缓存命中时直接返回结果;否则,通过给定的Callable类call方法获取结果并将结果缓存。<br/>
* 可以用一个cache对象缓存多种不同的数据,只需创建不同的Callable对象即可。
*/
Person person = cache2.get(key, new Callable<Person>() {
public Person call() throws ExecutionException {
System.out.println(key + " load in cache");
return getPerson(key);
} // 此时一般我们会进行相关处理,如到数据库去查询
private Person getPerson(String key) throws ExecutionException {
System.out.println(key + " query");
for (Person p : list) {
if (p.getId().equals(key))
return p;
}
return null;
}
});
System.out.println("======= sencond time ==========");
person = cache2.getIfPresent(key);
person = cache2.getIfPresent(key);
}
}
执行结果如下:
1 load in cache
1 query
======= sencond time ==========
第二次获取后也是直接从缓存中加载。
3、关于移除监听器
通过CacheBuilder.removalListener(RemovalListener),我们可以声明一个监听器,从而可以在缓存被移除时做一些其他的操作。当缓存被移除时,RemovalListener会获取移除bing通知[RemovalNotification],其中包含移除的key、value和RemovalCause。
示例代码如下:
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit; import org.junit.Test; import com.google.cacahe.Person;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.google.common.cache.RemovalListener;
import com.google.common.cache.RemovalNotification; public class TestGuavaCache {
@Test
public void testListener() throws ExecutionException {
CacheLoader<String, Person> loader = new CacheLoader<String, Person>() {
@Override
// 当本地缓存命没有中时,调用load方法获取结果并将结果缓存
public Person load(String key) throws ExecutionException {
System.out.println(key + " load in cache");
return getPerson(key);
}
// 此时一般我们会进行相关处理,如到数据库去查询
private Person getPerson(String key) throws ExecutionException {
System.out.println(key + " query");
return new Person(key, "zhang" + key);
}
}; // remove listener
RemovalListener<String, Person> removalListener = new RemovalListener<String, Person>() {
public void onRemoval(RemovalNotification<String, Person> removal) {
System.out.println("cause:" + removal.getCause() + " key:" + removal.getKey() + " value:"
+ removal.getValue());
}
}; LoadingCache<String, Person> cache = CacheBuilder.newBuilder()//
.expireAfterWrite(2, TimeUnit.MINUTES).maximumSize(1024).removalListener(removalListener).build(loader);
cache.get("1");// 放入缓存
cache.get("1");// 第二次获取(此时从缓存中获取)
cache.invalidate("1");// 移除缓存
cache.get("1");// 重新获取
cache.get("1");// 再次获取(此时从缓存中获取)
}
}
运行结果如下:
1 load in cache
1 query
cause:EXPLICIT key:1 value:Person [id=1, name=zhang1]
1 load in cache
1 query
三、其他相关方法
显式插入:该方法可以直接向缓存中插入值,如果缓存中有相同key则之前的会被覆盖。
cache.put(key, value);
显式清除:我们也可以对缓存进行手动清除。
cache.invalidate(key); //单个清除
cache.invalidateAll(keys); //批量清除
cache.invalidateAll(); //清除所有缓存项
基于时间的移除:
expireAfterAccess(long, TimeUnit); 该键值对最后一次访问后超过指定时间再移除
expireAfterWrite(long, TimeUnit) ;该键值对被创建或值被替换后超过指定时间再移除
基于大小的移除:指如果缓存的对象格式即将到达指定的大小,就会将不常用的键值对从cache中移除。
cacheBuilder.maximumSize(long)
size是指cache中缓存的对象个数。当缓存的个数开始接近size的时候系统就会进行移除的操作
缓存清除执行的时间
使用CacheBuilder构建的缓存不会"自动"执行清理和回收工作,也不会在某个缓存项过期后马上清理,也没有诸如此类的清理机制。它是在写操作时顺带做少量的维护工作(清理);如果写操作太少,读操作的时候也会进行少量维护工作。因为如果要自动地持续清理缓存,就必须有一个线程,这个线程会和用户操作竞争共享锁。在某些环境下线程创建可能受限制,这样CacheBuilder就不可用了。
Google Guava之--cache的更多相关文章
- Google Guava -缓存cache简单使用
package guavacache; import java.util.concurrent.ExecutionException; import java.util.concurrent.Time ...
- 使用google guava做内存缓存
google guava中有cache包,此包提供内存缓存功能.内存缓存需要考虑很多问题,包括并发问题,缓存失效机制,内存不够用时缓存释放,缓存的命中率,缓存的移除等等. 当然这些东西guava都考虑 ...
- (翻译)Google Guava Cache
翻译自Google Guava Cache This Post is a continuation of my series on Google Guava, this time covering G ...
- google guava cache缓存基本使用讲解
代码地址:https://github.com/vikde/demo-guava-cache 一.简介 guava cache是google guava中的一个内存缓存模块,用于将数据缓存到JVM内存 ...
- Google Guava Cache 全解析
Google guava工具类的介绍和使用https://blog.csdn.net/wwwdc1012/article/details/82228458 LoadingCache缓存使用(Loadi ...
- Google Guava官方教程(中文版)
Google Guava官方教程(中文版) 原文链接 译文链接 译者: 沈义扬,罗立树,何一昕,武祖 校对:方腾飞 引言 Guava工程包含了若干被Google的 Java项目广泛依赖 的核心库, ...
- google guava 基本工具
近期在项目中用到了google中的cache了解到guava里面的一些工具类和对集合的操作,封装的都比较下,没有时间自己去写,先做个标记, 参考文章如下: http://macrochen.iteye ...
- 初探Google Guava
Guava地址:https://github.com/google/guava 第一次接触我是在16年春github上,当时在找单机查缓存方法,google guava当初取名是因为JAVA的类库不好 ...
- SpringBoot 遇到 com.google.guava » guava 组件运行异常问题修复方案
环境 Apache Maven : 3.5.4 org.springframework.boot » spring-boot-starter-parent : 2.0.3.RELEASE io.spr ...
随机推荐
- Win10安装.net framework 4.0失败提示已是操作系统一部分如何解决
有位用户因为工作需求,所以想在win10系统电脑中安装microsoft .net framework 4.0.可是在安装过程中却失败了,还遇到提示"Microsoft.net framew ...
- 组合数学 - 母函数的运用 + 模板 --- hdu : 2082
找单词 Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submiss ...
- 关于SqlServer2012本地帮助文档安装失败问题
由于本人在前一段时间安装了SqlServer2012,安装后没有自带本地帮助文档,因为新的数据库版本微软捆绑了一个本地帮助文档查看器软件,所以在这个软件里面选择联机安装的时候,总是下载不成功,原因你们 ...
- WebApi传参总动员(三)
上篇介绍了如何从输入流中获取实体对象.本篇介绍以url形式传递参数.简单的参数不再赘述,这里主要实现形如(string name,Woman woman)这样的参数传递. 本篇及后面几章均涉及js调用 ...
- 行转列一定要sum
--SELECT 姓名 ,-- 课程 ,-- 分数--FROM tb UNPIVOT ( 分数 FOR 课程 IN ( [语文], [数学], [物理] ) ) t --)
- 几个gcc的扩展功能
-finstrument-functions constructor destructor __builtin_return_address http://linuxgazette.net/15 ...
- ahjesus linux连接阿里云ubuntu服务器并更改默认账号和密码,以及创建子账户
先确保本地Linux服务器SSH服务开启,如果没有开启直接执行指令:service sshd start 然后我们使用ssh指令进行远程登陆 ssh username@ip-address 输入pas ...
- js中this的理解
平常用this很多,对this的理解就是this是对应执行环境,然而很多时候效果并不是想要的,最近看了一些谈到this的笔记和书籍,总结下. 对this的误解: this是指向函数本身 先上个demo ...
- sublimeText插件推荐
工欲善其事必先利其器.sublimeText是前端开发工程师的一把利器,它的优点包含: 随时保留文件的修改 Goto Anything,智能搜索; 简单全面的插件体系; 代码地图; 快速启动 ... ...
- C#获取本地系统日期格式
我们可以通过使用DataTime这个类来获取当前的时间.通过调用类中的各种方法我们可以获取不同的时间:如:日期(2008-09-04).时间(12:12:12).日期+时间(2008-09-04 12 ...