【Guava】Google Guava本地高效缓存
1.Google,Guava本地高效缓存
Guva是google
开源的一个公共java库,类似于Apache Commons,
它提供了集合,反射,缓存,科学计算,xml,io等一些工具类库。cache只是其中的一个模块。使用Guva cache
能够方便快速的构建本地缓存。
2. 使用Guava构建第一个缓存
首先需要在maven项目中加入guava依赖
<dependency><groupId>com.google.guava</groupId><artifactId>guava</artifactId><version>25.0-jre</version>
</dependency>
使用Guava创建一个缓存
// 通过CacheBuilder构建一个缓存实例
Cache<String, String> cache = CacheBuilder.newBuilder().maximumSize(100) // 设置缓存的最大容量.expireAfterWrite(1, TimeUnit.MINUTES) // 设置缓存在写入一分钟后失效.concurrencyLevel(10) // 设置并发级别为10.recordStats() // 开启缓存统计.build();
// 放入缓存
cache.put("key", "value");
// 获取缓存
String value = cache.getIfPresent("key");expireAfterWrite 缓存一定时间内直接失效
expireAfterAccess 缓存被访问后,一定时间后失效
getIfPresent 不存在就返回null
代码演示了使用Guava创建了一个基于内存的本地缓存,并指定了一些缓存的参数,如缓存容量、缓存过期时间、并发级别等,随后通过put方法放入一个缓存并使用getIfPresent来获取它。
3.Cache与LoadingCache
Cache是通过CacheBuilder的build()方法构建,它是Gauva提供的最基本的缓存接口,并且它提供了一些常用的缓存api:
Cache<Object, Object> cache = CacheBuilder.newBuilder().build();
// 放入/覆盖一个缓存
cache.put("k1", "v1");
// 获取一个缓存,如果该缓存不存在则返回一个null值
Object value = cache.getIfPresent("k1");
// 获取缓存,当缓存不存在时,则通Callable进行加载并返回。该操作是原子
Object getValue = cache.get("k1", new Callable<Object>() {@Overridepublic Object call() throws Exception {return null;}
});
4.LoadingCache
LoadingCache继承自Cache,在构建LoadingCache时,需要通过CacheBuilder的build(CacheLoader<? super K1, V1> loader)
方法构建
CacheBuilder.newBuilder().build(new CacheLoader<String, String>() {@Overridepublic String load(String key) throws Exception {// 缓存加载逻辑...}});
它能够通过CacheLoader自发的加载缓存
LoadingCache<Object, Object> loadingCache = CacheBuilder.newBuilder().build(new CacheLoader<Object, Object>() {@Overridepublic Object load(Object key) throws Exception {return null;}});
// 获取缓存,当缓存不存在时,会通过CacheLoader自动加载,该方法会抛出ExecutionException异常
loadingCache.get("k1");
// 以不安全的方式获取缓存,当缓存不存在时,会通过CacheLoader自动加载,该方法不会抛出异常
loadingCache.getUnchecked("k1");
5.缓存的并发级别
Guava提供了设置并发级别的api,使得缓存支持并发的写入和读取。同ConcurrentHashMap类似Guava cache的并发也是通过分离锁实现。在一般情况下,将并发级别设置为服务器cpu核心数是一个比较不错的选择。
CacheBuilder.newBuilder()// 设置并发级别为cpu核心数.concurrencyLevel(Runtime.getRuntime().availableProcessors()) .build();
6.缓存的初始容量
我们在构建缓存时可以为缓存设置一个合理大小初始容量,由于Guava的缓存使用了分离锁的机制,扩容的代价非常昂贵。所以合理的初始容量能够减少缓存容器的扩容次数。
CacheBuilder.newBuilder()// 设置初始容量为100.initialCapacity(100).build();
使用基于最大容量的的回收策略时,我们需要设置2个必要参数:
maximumWeigh;用于指定最大容量。
Weigher;在加载缓存时用于计算缓存容量大小。
这里我们例举一个key和value都是String类型缓存:
CacheBuilder.newBuilder().maximumWeight(1024 * 1024 * 1024) // 设置最大容量为 1M// 设置用来计算缓存容量的Weigher.weigher(new Weigher<String, String>() { @Overridepublic int weigh(String key, String value) {return key.getBytes().length + value.getBytes().length;}}).build();
当缓存的最大数量/容量逼近或超过我们所设置的最大值时,Guava就会使用LRU算法对之前的缓存进行回收。
7.基于软/弱引用的回收
基于引用的回收策略,是java中独有的。在java中有对象自动回收机制,依据程序员创建对象的方式不同,将对象由强到弱分为强引用、软引用、弱引用、虚引用。对于这几种引用他们有以下区别
7.1 强引用
强引用是使用最普遍的引用。如果一个对象具有强引用,那垃圾回收器绝不会回收它。
Object o=new Object(); // 强引用
当内存空间不足,垃圾回收器不会自动回收一个被引用的强引用对象,而是会直接抛出OutOfMemoryError错误,使程序异常终止。
7.2 软引用
相对于强引用,软引用是一种不稳定的引用方式,如果一个对象具有软引用,当内存充足时,GC不会主动回收软引用对象,而当内存不足时软引用对象就会被回收。
SoftReference<Object> softRef=new SoftReference<Object>(new Object()); // 软引用
Object object = softRef.get(); // 获取软引用
使用软引用能防止内存泄露,增强程序的健壮性。但是一定要做好null检测。
7.3 弱引用
弱引用是一种比软引用更不稳定的引用方式,因为无论内存是否充足,弱引用对象都有可能被回收。
WeakReference<Object> weakRef = new WeakReference<Object>(new Object()); // 弱引用
Object obj = weakRef.get(); // 获取弱引用
7.4 虚引用
而虚引用这种引用方式就是形同虚设,因为如果一个对象仅持有虚引用,那么它就和没有任何引用一样。在实践中也几乎没有使用。
在Guava cache中支持,软/弱引用的缓存回收方式。使用这种方式能够极大的提高内存的利用率,并且不会出现内存溢出的异常。
CacheBuilder.newBuilder().weakKeys() // 使用弱引用存储键。当键没有其它(强或软)引用时,该缓存可能会被回收。.weakValues() // 使用弱引用存储值。当值没有其它(强或软)引用时,该缓存可能会被回收。.softValues() // 使用软引用存储值。当内存不足并且该值其它强引用引用时,该缓存就会被回收.build();
通过软/弱引用的回收方式,相当于将缓存回收任务交给了GC,使得缓存的命中率变得十分的不稳定,在非必要的情况下,还是推荐基于数量和容量的回收。
8.显式回收
在缓存构建完毕后,我们可以通过Cache提供的接口,显式的对缓存进行回收,例如:
// 构建一个缓存
Cache<String, String> cache = CacheBuilder.newBuilder().build();
// 回收key为k1的缓存
cache.invalidate("k1");// 批量回收key为k1、k2的缓存
List<String> needInvalidateKeys = new ArrayList<>();
needInvalidateKeys.add("k1");
needInvalidateKeys.add("k2");
cache.invalidateAll(needInvalidateKeys);
// 回收所有缓存
cache.invalidateAll();
缓存的过期策略与刷新
Guava也提供了缓存的过期策略和刷新策略。
9.缓存过期策略
缓存的过期策略分为固定时间和相对时间。
固定时间一般是指写入后多长时间过期,例如我们构建一个写入10分钟后过期的缓存:
CacheBuilder.newBuilder()
.expireAfterWrite(10, TimeUnit.MINUTES) // 写入10分钟后过期.build();
// java8后可以使用Duration设置
CacheBuilder.newBuilder().expireAfterWrite(Duration.ofMinutes(10)).build();
相对时间一般是相对于访问时间,也就是每次访问后,会重新刷新该缓存的过期时间,这有点类似于servlet中的session过期时间,例如构建一个在10分钟内未访问则过期的缓存:
CacheBuilder.newBuilder().expireAfterAccess(10, TimeUnit.MINUTES) //在10分钟内未访问则过期.build();
// java8后可以使用Duration设置
CacheBuilder.newBuilder().expireAfterAccess(Duration.ofMinutes(10)).build();
10.缓存刷新
在Guava cache中支持定时刷新和显式刷新两种方式,其中只有LoadingCache能够进行定时刷新。
11 定时刷新
在进行缓存定时刷新时,我们需要指定缓存的刷新间隔,和一个用来加载缓存的CacheLoader,当达到刷新时间间隔后,下一次获取缓存时,会调用CacheLoader的load方法刷新缓存。例如构建个刷新频率为10分钟的缓存:
CacheBuilder.newBuilder()// 设置缓存在写入10分钟后,通过CacheLoader的load方法进行刷新.refreshAfterWrite(10, TimeUnit.SECONDS)// jdk8以后可以使用 Duration// .refreshAfterWrite(Duration.ofMinutes(10)).build(new CacheLoader<String, String>() {@Overridepublic String load(String key) throws Exception {// 缓存加载逻辑...}});
12 显式刷新
在缓存构建完毕后,我们可以通过Cache提供的一些借口方法,显式的对缓存进行刷新覆盖,例如:
// 构建一个缓存
Cache<String, String> cache = CacheBuilder.newBuilder().build();
// 使用put进行覆盖刷新
cache.put("k1", "v1");
// 使用Map的put方法进行覆盖刷新
cache.asMap().put("k1", "v1");
// 使用Map的putAll方法进行批量覆盖刷新
Map<String,String> needRefreshs = new HashMap<>();
needRefreshs.put("k1", "v1");
cache.asMap().putAll(needRefreshs);
// 使用ConcurrentMap的replace方法进行覆盖刷新
cache.asMap().replace("k1", "v1");
对于LoadingCache,由于它能够自动的加载缓存,所以在进行刷新时,不需要显式的传入缓存的值:
LoadingCache<String, String> loadingCache = CacheBuilder.newBuilder().build(new CacheLoader<String, String>() {@Overridepublic String load(String key) throws Exception {// 缓存加载逻辑return null;}});
// loadingCache 在进行刷新时无需显式的传入 value
loadingCache.refresh("k1");
原文:https://rumenz.com/rumenbiji/google-guava-java.html
【Guava】Google Guava本地高效缓存相关推荐
- Google,Guava本地高效缓存
Guva是google开源的一个公共java库,类似于Apache Commons,它提供了集合,反射,缓存,科学计算,xml,io等一些工具类库. cache只是其中的一个模块.使用Guva cac ...
- Java类库Google Guava学习
参考 官网 https://github.com/google/guava Google Guava官方教程(中文版) | 并发编程网 – ifeve.com 一篇让你熟练掌握Google Guava ...
- 【Guava】Guava Cache的refresh和expire刷新机制
1.概述 转载:https://www.cnblogs.com/liuxiaochong/p/13613071.html 总览参考:[Guava]Google Guava本地高效缓存 案例参考:[gu ...
- Google Guava Cache高效本地缓存
目录 Guava Cache使用需求和场景 需求 场景 缓存设置 缓存的并发级别 缓存的初始容量设置 设置最大存储 缓存清除策略 基于存活时间的清除策略 基于容量的清除策略 基于权重的清除 策略 显式 ...
- java本地缓存 google guava
本地缓存产生背景: 本地缓存是指在我们本地的物理空间开辟出一片物理空间,专门用来存储我们需要向服务器端频繁需要的数据, 比如前端页面需要频繁的向后台访问某些数据,这时候我们每次都去数据库查找数据再返回 ...
- Google guava第一讲:guava缓存实战/使用场景/缓存清理/最佳实践/caffeine实战
Guava缓存实战及使用场景 摘要:本文是Google guava 第一件,本文先介绍了为什么使用Guava Cache缓存,然后讲解了使用方法及底层数据结构,结合实际业务,讲解使用guava过程中踩 ...
- 多级缓存之Google Guava的实现方案
文章目录 背景 如何创建? pom引入依赖 CacheLoader方式 何时使用? 案例 CacheBuilder 的详细方法 Callable方式 何时使用? 案例 如何删除? 被动 基于数据大小的 ...
- Java内存缓存-通过Google Guava创建缓存
谷歌Guava缓存 Guava介绍 Guava是Google guava中的一个内存缓存模块,用于将数据缓存到JVM内存中.实际项目开发中经常将一些公共或者常用的数据缓存起来方便快速访问. Guava ...
- Google Guava缓存实现接口的限流
一.项目背景 最近项目中需要进行接口保护,防止高并发的情况把系统搞崩,因此需要对一个查询接口进行限流,主要的目的就是限制单位时间内请求此查询的次数,例如1000次,来保护接口. 参考了 开涛的博客聊聊 ...
最新文章
- RDKit | 可视化官能团, 分子聚类, 相似图, 化合物高亮和骨架网络
- switch case穿透Java_Switch语句的case穿透
- FPGA之道(65)代码中的约束信息(二)乘法器的相关约束
- oracle 监听主机,Oracle 监听
- 3·15,你“信”了吗
- 易混淆知识点(3):b和strong的真正区别在哪?
- 如何在Mac上设置语音整点报时
- p12文件和mobileprovision文件导入到xcode如何使用
- 迅捷PDF虚拟打印机怎么打印成pdf文件
- Pycharm CPU占用100%
- JavaScript---网络编程(9-1)--DHTML技术演示(2-1)-表格创建的几种方式
- 深入浅出 RPC - 浅出篇
- 浅析Chrome Packaged Apps
- vue项目中实现录屏两种方式rrweb和RecordRTC
- Macbook windows 10系统下录屏软件无法录制系统声音的问题
- 毕业之后所有面试总结
- 【转载】C++ pair的基本用法总结(整理)
- XXTEA 加解密算法的 Python 实现
- 在线表格编辑插件handsontable使用
- Go语言学习史诗级教程-带你领略GoLang语言新世界
热门文章
- 小米产品都是中低端手机、没技术?雷军回应:我很郁闷
- 华为正式宣布全场景AI计算框架MindSpore开源 降低AI开发门槛
- Android 11首个预览版发布:打开飞行模式蓝牙耳机不断连
- 对刚iPad!华为最强Pad发布,独揽四项全球第一,3299元起!
- 何小鹏“维权”事后谈造车:心很累 曾购上千瓶白酒缓解压力
- 江淮汽车涉嫌排放造假 罚款1.7亿
- 最耐用的手机盘点 网友:我这个能用到品牌商“破产”!
- GPIO应用开发方法【ZT】
- Android之深入WebView
- BootLoader简介——linux内核的引导