Guva是google开源的一个公共java库,类似于Apache Commons,它提供了集合,反射,缓存,科学计算,xml,io等一些工具类库。
cache只是其中的一个模块。使用Guva cache能够方便快速的构建本地缓存。

文章目录

  • 使用Guava构建第一个缓存
    • LoadingCache
  • 缓存的并发级别

使用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来获取它。

##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;}
});

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");

缓存的并发级别

Guava提供了设置并发级别的api,使得缓存支持并发的写入和读取。同ConcurrentHashMap类似Guava cache的并发也是通过分离锁实现。在一般情况下,将并发级别设置为服务器cpu核心数是一个比较不错的选择。

CacheBuilder.newBuilder()// 设置并发级别为cpu核心数.concurrencyLevel(Runtime.getRuntime().availableProcessors()) .build();

##缓存的初始容量

我们在构建缓存时可以为缓存设置一个合理大小初始容量,由于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算法对之前的缓存进行回收。

##基于软/弱引用的回收

基于引用的回收策略,是java中独有的。在java中有对象自动回收机制,依据程序员创建对象的方式不同,将对象由强到弱分为强引用、软引用、弱引用、虚引用。对于这几种引用他们有以下区别


** 强引用**

强引用是使用最普遍的引用。如果一个对象具有强引用,那垃圾回收器绝不会回收它。

Object o=new Object();   //  强引用

当内存空间不足,垃圾回收器不会自动回收一个被引用的强引用对象,而是会直接抛出OutOfMemoryError错误,使程序异常终止。

软引用

相对于强引用,软引用是一种不稳定的引用方式,如果一个对象具有软引用,当内存充足时,GC不会主动回收软引用对象,而当内存不足时软引用对象就会被回收。

SoftReference<Object> softRef=new SoftReference<Object>(new Object()); // 软引用
Object object = softRef.get(); // 获取软引用

使用软引用能防止内存泄露,增强程序的健壮性。但是一定要做好null检测。

弱引用

弱引用是一种比软引用更不稳定的引用方式,因为无论内存是否充足,弱引用对象都有可能被回收。

WeakReference<Object> weakRef = new WeakReference<Object>(new Object()); // 弱引用
Object obj = weakRef.get(); // 获取弱引用

虚引用

而虚引用这种引用方式就是形同虚设,因为如果一个对象仅持有虚引用,那么它就和没有任何引用一样。在实践中也几乎没有使用。

在Guava cache中支持,软/弱引用的缓存回收方式。使用这种方式能够极大的提高内存的利用率,并且不会出现内存溢出的异常。

CacheBuilder.newBuilder().weakKeys() // 使用弱引用存储键。当键没有其它(强或软)引用时,该缓存可能会被回收。.weakValues() // 使用弱引用存储值。当值没有其它(强或软)引用时,该缓存可能会被回收。.softValues() // 使用软引用存储值。当内存不足并且该值其它强引用引用时,该缓存就会被回收.build();

通过软/弱引用的回收方式,相当于将缓存回收任务交给了GC,使得缓存的命中率变得十分的不稳定,在非必要的情况下,还是推荐基于数量和容量的回收。

##显式回收

在缓存构建完毕后,我们可以通过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也提供了缓存的过期策略和刷新策略。

###缓存过期策略

缓存的过期策略分为固定时间和相对时间。

固定时间一般是指写入后多长时间过期,例如我们构建一个写入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();

##缓存刷新

在Guava cache中支持定时刷新和显式刷新两种方式,其中只有LoadingCache能够进行定时刷新。

定时刷新

在进行缓存定时刷新时,我们需要指定缓存的刷新间隔,和一个用来加载缓存的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 {// 缓存加载逻辑...}});

显式刷新

在缓存构建完毕后,我们可以通过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

Google,Guava本地高效缓存相关推荐

  1. 【Guava】Google Guava本地高效缓存

    1.Google,Guava本地高效缓存 Guva是google开源的一个公共java库,类似于Apache Commons,它提供了集合,反射,缓存,科学计算,xml,io等一些工具类库.cache ...

  2. Google Guava Cache高效本地缓存

    目录 Guava Cache使用需求和场景 需求 场景 缓存设置 缓存的并发级别 缓存的初始容量设置 设置最大存储 缓存清除策略 基于存活时间的清除策略 基于容量的清除策略 基于权重的清除 策略 显式 ...

  3. java本地缓存 google guava

    本地缓存产生背景: 本地缓存是指在我们本地的物理空间开辟出一片物理空间,专门用来存储我们需要向服务器端频繁需要的数据, 比如前端页面需要频繁的向后台访问某些数据,这时候我们每次都去数据库查找数据再返回 ...

  4. 多级缓存之Google Guava的实现方案

    文章目录 背景 如何创建? pom引入依赖 CacheLoader方式 何时使用? 案例 CacheBuilder 的详细方法 Callable方式 何时使用? 案例 如何删除? 被动 基于数据大小的 ...

  5. google guava 入门教程

    Guava(瓜娃)学习笔记 (代码下载地址) Guava工程包含了若干被google的java项目广泛依赖的核心库,例如:集合 [collections] .缓存 [caching] .原生类型支持 ...

  6. Google guava第一讲:guava缓存实战/使用场景/缓存清理/最佳实践/caffeine实战

    Guava缓存实战及使用场景 摘要:本文是Google guava 第一件,本文先介绍了为什么使用Guava Cache缓存,然后讲解了使用方法及底层数据结构,结合实际业务,讲解使用guava过程中踩 ...

  7. Java内存缓存-通过Google Guava创建缓存

    谷歌Guava缓存 Guava介绍 Guava是Google guava中的一个内存缓存模块,用于将数据缓存到JVM内存中.实际项目开发中经常将一些公共或者常用的数据缓存起来方便快速访问. Guava ...

  8. Guava 本地缓存使用教程

    文章目录 准备工作 创建缓存 使用缓存 Cache 读取缓存 LoadingCache 读取缓存 修改缓存 Cache 修改缓存 LoadingCache 修改缓存 其他方法 在前面的文章 Sprin ...

  9. GUAVA本地缓存01_概述、优缺点、创建方式、回收机制、监听器、统计、异步锁定

    文章目录 ①. 本地缓存 - 背景 ②. 本地缓存 - 优缺点 ③. Guava Cache介绍 ④. Guava - 三种创建方式 ⑤. Guava - 如何回收缓存 ⑥. Guava - 移除监听 ...

最新文章

  1. 智源学者朱军获2020年“科学探索奖”
  2. SDUT2165:Crack Mathmen(快速幂)
  3. python求乘积内建函数_Python中的内建函数(Built_in Funtions)
  4. ストアドプロシージャ(存储过程)
  5. AAAI 2019 Oral | 让TA说你想听的—基于音/视频特征解离的讲述者人脸生成
  6. UTF-8编码规则(转)
  7. mysql增删改查 工具类_Hibernate增删改查数据库之二工具类
  8. 初识MQ--mq常见技术介绍
  9. phpstorm PHP language level无法选择
  10. mysql 导致iis 假死_php使用MySql函数导致Apache(iis)崩溃的问题解决方案
  11. 《UNIX网络编程 卷2:进程间通信(第2版)》——1.4 名字空间
  12. 拓端tecdat|R语言使用马尔可夫链对营销中的渠道归因建模
  13. 2020-06-28
  14. window下开启mysql慢查询和分割慢查询日志
  15. MAVEN 仓库加速 阿里云镜像
  16. Matlab GUI界面设计
  17. 数据挖掘概念与技术——读书笔记(1)
  18. 吃完饭后,到底是躺着、坐着、站着还是运动?看完终于不纠结了
  19. 运行提速:让电脑从拖拉机引擎变成宝马引擎必备知识
  20. 使用ArrayList集合,对其添加10个不同的元素,并使用Iterator遍历该集合

热门文章

  1. C结构体之位域(位段)
  2. Linux文件及文件内容的查找-转
  3. LeetCode 724. Find Pivot Index
  4. 蓝桥杯 ALGO-4 算法训练 结点选择
  5. 蓝桥杯 ADV-109 算法提高 征税程序
  6. oracle 时间戳生成语句(秒级+毫秒级)
  7. java 实现WebService 以及不同的调用方式
  8. SylixOS lsusb命令解析
  9. 【EASYDOM系列教程】之属性操作
  10. hausaufgabe--python 11-List slice