guava缓存
原创大约 3 分钟
从CPU高速缓存
、操作系统缓存
到HTTP缓存
,再到静态文件缓存
,IT系统中到处都有缓存的身影存在。
按照范围不同,缓存又分为进程内缓存
和进程外缓存
按照架构不同,它又分为本地缓存
和分布式缓存
。
而进程内缓存
又分为组件缓存
和第三方缓存
。
组件缓存
是在程序内使用变量来存储数据,例如,Java中的List
、Map
和Set
等集合组件就常常用作这样的缓存。第三方缓存
是利用第三方组件在系统运行时存储数据,例如,目前用的比较多的Ehcache和Guava Cache。
Ehcache和Guava Cache主要的区别如下。
Ehcache属于非常重量级的持久化进程缓存框架,Guava Cache是基于
ConCurrentHashMap
的轻量级LRU。Ehcache支持数据持久化,而Guava Cache没有持久化。
Ehcache有集群解决方案,Guava Cache没有。
Ehcache代码及本身占用内存庞大,对性能会造成影响。
Guava Cache的使用很简单。
引入依赖。
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>30.0-jre</version>
</dependency>
然后编写测试代码。
package com.xiangwang.commons.cache;
import com.google.common.cache.*;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
/**
* Cache测试类
*
*/
public class GuavaCache {
public static void main(String[] args) throws ExecutionException, InterruptedException {
// 构建一个Cache缓存对象
Cache<String, String> cache = CacheBuilder.newBuilder().build();
cache.put("key", "hello world");
System.out.println(cache.getIfPresent("key"));
// 访问一个不存在的缓存
System.out.println(cache.getIfPresent("nocache"));
// Guava Cache可以指定缓存所能够存储的最大记录数量
// 当Cache中的记录数量达到最大值后,如果再调用put方法向其中添加对象
// Guava会先从记录中选择一条删除掉,腾出空间后再将新的对象存储到Cache中
Cache<String,String> cache2 = CacheBuilder.newBuilder()
.maximumSize(2)
.build();
cache2.put("a","1");
cache2.put("b","2");
cache2.put("c","3");
System.out.println("第一个值:" + cache2.getIfPresent("a"));
System.out.println("第二个值:" + cache2.getIfPresent("b"));
System.out.println("第三个值:" + cache2.getIfPresent("c"));
// 缓存中最经常使用的就是过期设置,尤其是在存储token的时候
// Guava Cache不会自动地清理和删除数据,也不会在值到期后清理和删除数据
Cache<String,String> cache3 = CacheBuilder.newBuilder()
.maximumSize(2)
.expireAfterWrite(3, TimeUnit.SECONDS)// 过期时间3秒
.build();
cache3.put("key","value");
int time = 1;
while(true) {
System.out.println("第" + time++ + "次key的值为:" + cache3.getIfPresent("key"));
// expireAfterWrite可以实现写入后3秒过期,但有个小问题:它并不是3秒后立即过期,
// 而是在三秒过后再访问一次时才能删除kv值
// expireAfterAccess方法则是读取后3秒过期,如果3秒之内一直读取,那么这个数据就一直不会过期
if (6 == time) {
break;
}
Thread.sleep(1000);
}
// 构建一个LoadingCache对象
// 和Cache不同的是,创建LoadingCache需要提供自己的CacheLoader实现
LoadingCache<String, String> loadingCache = CacheBuilder.newBuilder()
.build(
new CacheLoader<String, String>() {
public String load(String key) throws Exception {
return "default";// 返回一个默认值
}
});
loadingCache.put("key", "xiangwang");
String value = loadingCache.get("key");
System.out.println(value);
value = loadingCache.get("key2");
System.out.println(value);
}
}
一般情况下,缓存要么是用来临时存储一个结果,要么是用来存储一个高频访问的数据。
因此,基于这两类场景,对于缓存的使用也基本上限于过期自动删除和常规的读写操作。
那种给缓存加监听、统计缓存信息这类应用场景或功能,在实际开发工作中极少出现。
感谢支持
更多内容,请移步《超级个体》。