缓存在很多场景下都是相当有用的。例如,计算或检索一个值的代价很高,并且对同样的输入需要不止一次获取值的时候,就应当考虑使用缓存。
Guava Cache与ConcurrentMap很相似,但也不完全一样。最基本的区别是ConcurrentMap会一直保存所有添加的元素,直到显式地移除。相对地,
Guava Cache为了限制内存占用,通常都设定为自动回收元素。在某些场景下,尽管LoadingCache 不回收元素,它也是很有用的,因为它会自动加载缓存。
LoadingCache是附带CacheLoader构建而成的缓存实现。创建自己的CacheLoader通常只需要简单地实现V load(K key) throws Exception方法。
例如,你可以用下面的代码构建LoadingCache:
@Test
public void LoadingCache() throws Exception{
LoadingCache<String,String> cahceBuilder=CacheBuilder
.newBuilder().maximumSize(10000).expireAfterAccess(10, TimeUnit.MINUTES)
.build(new CacheLoader<String, String>(){
@Override
public String load(String key) throws Exception {
return createExpensiveGraph(key);
}
private String createExpensiveGraph(String key) {
System.out.println("load into cache!");
return "hello "+key+"!";
}
});
cahceBuilder.get("2");
cahceBuilder.get("3");
//第二次就直接从缓存中取出
cahceBuilder.get("2");
}
Callable缓存的实现
所有类型的Guava Cache,不管有没有自动加载功能,都支持get(K, Callable<V>)方法。这个方法返回缓存中相应的值,或者用给定的Callable运算并把结果加入到缓存中。
在整个加载方法完成前,缓存项相关的可观察状态都不会更改。这个方法简便地实现了模式"如果有缓存则返回;否则运算、缓存、然后返回"
@Test
public void callableCache()throws Exception{
Cache<String, String> cache = CacheBuilder.newBuilder().maximumSize(1000).expireAfterAccess(10, TimeUnit.MINUTES).build();
//这里可以手動进行缓存
cache.put("1", "I'm in chche");
//-----------------------------------------------
final String key1 = "1";
String resultVal = cache.get(key1, new Callable<String>() {
public String call() {
return createExpensiveGraph(key1);
}
});
System.out.println("1 value : " + resultVal);
//-------------------------------------------------
resultVal = cache.get("2", new Callable<String>() {
public String call() {
return createExpensiveGraph(key1);
}
});
System.out.println("2 value : " + resultVal);
//==================================================
}
protected String createExpensiveGraph(String string) {
return "hello "+string+"!";
}