Guava Cache有一些优点如下 :
1. 线程安全的缓存, 与ConcurrentMap相似(前者更"好"), 在高并发情况下、能够正常缓存更新以及返回.
2. 提供了三种基本的缓存回收方式 : 基于容量回收定时回收基于引用回收(本文没有提及引用回收).
3. 提供了两种定时回收:按照写入时间, 最早写入的最先回收;按照访问时间,最早访问的最早回收.
4. 可以监控缓存加载/命中情况.
5. 使用方便、简单.


1. 最基础的例子[CacheBuilder]

// 新建CacheBuilder
Cache<Integer, String> cache = CacheBuilder.newBuilder().build();
cache.put(1, "a");
cache.put(2, "b");
System.out.println(cache.getIfPresent(1)); // 输出: a
System.out.println(cache.getIfPresent(3)); // 输出: null
System.out.println(cache.getAllPresent(new ArrayList<Integer>(){{
add(1);
add(2);
}})); // 输出: {1=a, 2=b}

2. 若无缓存时,自定义缓存值[CacheLoader、get()]

// 遇到不存在的key,定义默认缓存值
// 1. 在cache定义时设置通用缓存模版
LoadingCache<Integer, String> cache1 = CacheBuilder.newBuilder().build(
new CacheLoader<Integer, String>() {
@Override
public String load(Integer key) throws Exception {
return "hellokey" + key;
}
}
);
cache1.put(1, "a");
System.out.println(cache1.getIfPresent(1)); // 输出: a
try {
System.out.println(cache1.getAll(new ArrayList<Integer>(){{ // getAll()将没有命中的key调用load()方法去加载数据
add(1);
add(2);
}})); // 输出: {1=a, 2=hellokey2}
System.out.println(cache1.get(3)); // 输出: hellokey3
} catch (ExecutionException e) {
e.printStackTrace();
} // 2. 在获取缓存值时设置缓存
Cache<Integer, String> cache2 = CacheBuilder.newBuilder().build();
cache2.put(1, "a");
System.out.println(cache2.getIfPresent(1)); // 输出: a
try {
String value = cache2.get(2, () -> "hellokey2");
System.out.println(value); // 输出: hellokey2
} catch (ExecutionException e) {
e.printStackTrace();
}

3. 控制缓存的大小/多少[.maximumSize()、.maximumWeight()]

// ps. .maximumSize(long),.maximumWeight(long)互斥,build()只可以二选一
// 1. 基于缓存多少
Cache<Integer, String> cache1 = CacheBuilder.newBuilder()
.maximumSize(2L) // 设置缓存上限,最多两个
.build();
cache1.put(1, "a");
cache1.put(2, "b");
cache1.put(3, "c");
System.out.println(cache1.asMap()); // 输出: {3=c, 2=b}
System.out.println(cache1.getIfPresent(2)); // 输出: b
cache1.put(4, "d");
System.out.println(cache1.asMap()); // 输出: {2=b, 4=d} // 2. 基于缓存大小
Cache<Integer, Integer> cache2 = CacheBuilder.newBuilder()
.maximumWeight(100L) // 指定最大总重
.weigher((Weigher<Integer, Integer>) (key, value) -> {
if (value % 2 == 0) {
return 20; // 偶数,则权重为20
} else {
return 5; // 非偶数,则权重为5
}
}) // 设置权重函数
.build();
for (int i = 0; i <= 20; i += 2) {
cache2.put(i, i);
}
System.out.println(cache2.asMap()); // 输出: {20=20, 18=18, 16=16, 14=14}
cache2.invalidateAll(); // 清除所有的缓存
for (int i = 0; i <= 20; i += 1) {
cache2.put(i, i);
}
System.out.println(cache2.asMap()); // 输出: {20=20, 19=19, 18=18, 17=17, 16=16, 14=14, 11=11}

4. 控制缓存回收的时间[.expireAfterWrite()、.expireAfterAccess()]

// 1. 设置缓存写入后多久过期
Cache<Integer, Integer> cache1 = CacheBuilder.newBuilder()
.expireAfterWrite(2, TimeUnit.SECONDS) // 缓存写入2s后过期
.build();
cache1.put(1,1);
System.out.println(cache1.asMap()); // 输出: {1=1}
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(cache1.asMap()); // 输出: {} // 2. 设置缓存读取后多久过期
Cache<Integer, Integer> cache2 = CacheBuilder.newBuilder()
.expireAfterAccess(2, TimeUnit.SECONDS) // 缓存读取2s后过期
.build();
cache2.put(1,1);
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
cache2.getIfPresent(1);
System.out.println(cache2.asMap()); // 输出: {1=1}
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(cache2.asMap()); // 输出: {}

5. 缓存更新[.refreshAfterWrite()]

// 设置更新时间, 定时去更新缓存中的数据
LoadingCache<String, String> cache = CacheBuilder.newBuilder()
.refreshAfterWrite(2, TimeUnit.SECONDS) // 缓存写入2s后更新
.build(new CacheLoader<String, String>() {
@Override
public String load(String key) throws Exception {
return UUID.randomUUID().toString(); // 假设是个查库操作之类的..
}
});
cache.put("1", "1");
System.out.println(cache.getIfPresent("1")); // 输出: 1
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(cache.getIfPresent("1")); // 输出: a6c1bf6f-61a7-46cb-99d9-ef7a81a7cacc
cache.refresh("1"); // 刷新key="1"的值,不需要等待更新时间
System.out.println(cache.getIfPresent("1")); // 输出: bf4912c1-b3a4-45f7-a50a-de2bb98757db

6. 手动清除缓存[.invalidate()、.invalidateAll()]

// 清除缓存中的数据
Cache<Integer, String> cache = CacheBuilder.newBuilder().build();
cache.put(1, "a");
System.out.println(cache.asMap()); // 输出: {1=a}
cache.invalidateAll(); // 清除所有缓存
System.out.println(cache.asMap()); // 输出: {}
cache.put(2, "b");
System.out.println(cache.asMap()); // 输出: {2=b}
cache.invalidate(2); // 清除指定缓存
System.out.println(cache.asMap()); // 输出: {}
cache.put(1, "a");
cache.put(2, "b");
cache.put(3, "c");
System.out.println(cache.asMap()); // 输出: {2=b, 1=a, 3=c}
cache.invalidateAll(new ArrayList<Integer>() {{ // 批量清除缓存
add(1);
add(2);
}});
System.out.println(cache.asMap()); // 输出: {3=c}

7. 设置监听器[.removalListener()]

// 设置移除监听器(ps. 当移除缓存时,会打印出被移除缓存的信息(基于模版格式))
LoadingCache<Integer, Integer> cache = CacheBuilder.newBuilder()
.expireAfterWrite(2, TimeUnit.SECONDS) // 设置2s后过期时间
.removalListener(notification -> System.out.println(
"remove key[" + notification.getKey()
+ "],value[" + notification.getValue()
+ "],remove reason[" + notification.getCause() + "]")
) // 设置移除监听器,并设置输出模版
.build(
new CacheLoader<Integer, Integer>() {
@Override
public Integer load(Integer key) throws Exception {
return 2; // 当无值时, 设置默认值
}
}
);
cache.put(1, 1);
cache.put(2, 2);
System.out.println(cache.asMap()); // 输出: {2=2, 1=1}
cache.invalidateAll();
System.out.println(cache.asMap()); // 输出: {}
cache.put(3, 3);
try {
// ps. 如果定义的CacheLoader没有声明任何检查型异常,则可以通过getUnchecked()取值
System.out.println(cache.getUnchecked(3)); // 输出: 3
Thread.sleep(3000);
System.out.println(cache.getUnchecked(3)); // 输出: 2
} catch (InterruptedException e) {
e.printStackTrace();
}

8. 自带的统计功能[.recordStats()]

// 开启统计,并查看统计信息
LoadingCache<String, String> cache = CacheBuilder.newBuilder()
.recordStats() // 开启统计功能
.refreshAfterWrite(2, TimeUnit.SECONDS) // 缓存写入2s后更新
.build(new CacheLoader<String, String>() {
@Override
public String load(String key) throws Exception {
return UUID.randomUUID().toString(); // 假设是个查库操作之类的..
}
});
cache.put("1", "a");
System.out.println(cache.asMap()); // 输出: {1=a}
System.out.println(cache.stats()); // 输出: CacheStats{hitCount=0, missCount=0, loadSuccessCount=0, loadExceptionCount=0, totalLoadTime=0, evictionCount=0}
cache.getIfPresent("2");
System.out.println(cache.asMap()); // 输出: {1=a}
System.out.println(cache.stats()); // 输出: CacheStats{hitCount=0, missCount=1, loadSuccessCount=0, loadExceptionCount=0, totalLoadTime=0, evictionCount=0}
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
cache.getIfPresent("1");
System.out.println(cache.asMap()); // 输出: {1=0207bb01-7b3c-4b66-b575-9fb2c5511a96}
System.out.println(cache.stats()); // 输出: CacheStats{hitCount=1, missCount=1, loadSuccessCount=1, loadExceptionCount=0, totalLoadTime=21118733, evictionCount=0}
/**
* hitCount; // 缓存命中数
* missCount; // 缓存未命中数
* loadSuccessCount; // load成功数
* loadExceptionCount; // load异常数
* totalLoadTime; // load的总共耗时
* evictionCount; // 缓存项被回收的总数,不包括显式清除
*/

9. 显示缓存中的数据[.asMap()]

// asMap视图
Cache<Integer, String> cache = CacheBuilder.newBuilder().build();
cache.put(1, "a");
cache.put(2, "b");
cache.put(3, "c");
cache.asMap(); // 返回的是个ConcurrentMap
System.out.println(cache.asMap().containsKey(1)); // 输出: true
System.out.println(cache.asMap().containsValue("b")); // 输出: true
System.out.println(cache.asMap().get(1)); // 输出: a
System.out.println(cache.asMap().put(5, "e")); // 输出: null
System.out.println(cache.asMap().entrySet()); // 输出: [5=e, 2=b, 1=a, 3=c]
System.out.println(cache.asMap()); // 输出: {5=e, 2=b, 1=a, 3=c}

guava缓存的更多相关文章

  1. Guava缓存器源码分析——删除消息

    Guava缓存器的删除消息机制 测试代码——             LoadingCache<String, Integer> cache = CacheBuilder.newBuild ...

  2. Guava缓存器源码分析——缓存统计器

    Guava缓存器统计器实现: 全局统计器——         1.CacheBuilder的静态成员变量Supplier<StatsCounter> CACHE_STATS_COUNTER ...

  3. guava缓存底层实现

    摘要 guava的缓存相信很多人都有用到, Cache<String, String> cache = CacheBuilder.newBuilder() .expireAfterWrit ...

  4. Google Guava缓存实现接口的限流

    一.项目背景 最近项目中需要进行接口保护,防止高并发的情况把系统搞崩,因此需要对一个查询接口进行限流,主要的目的就是限制单位时间内请求此查询的次数,例如1000次,来保护接口. 参考了 开涛的博客聊聊 ...

  5. springboot集成Guava缓存

    很久没有写博客了,这段时间一直忙于看论文,写论文,简直头大,感觉还是做项目比较舒服,呵呵,闲话不多说,今天学习了下Guava缓存,这跟Redis类似的,但是适用的场景不一样,学习下吧.今天我们主要是s ...

  6. spring中添加google的guava缓存(demo)

    1.pom文件中配置 <dependencies> <dependency> <groupId>org.springframework</groupId> ...

  7. guava缓存设置return null一直报错空指针

    guava缓存设置return null一直报错空指针 因为缓存不允许返回为空

  8. spring boot使用guava缓存

    1.pom中插入依赖: <!--guava缓存cache--> <dependency> <groupId>com.google.guava</groupId ...

  9. guava缓存批量获取的一个坑

    摘要 Guava Cache是Google开源的Java工具集库Guava里的一款缓存工具,一直觉得使用起来比较简单,没想到这次居然还踩了一个坑 背景 功能需求抽象出来很简单,就是将数据库的查询sth ...

  10. guava缓存第一篇

    guava缓存主要有2个接口,Cache和LoadingCache. Cache,全类名是com.google.common.cache.Cache,支持泛型.Cache<K, V>. L ...

随机推荐

  1. python中如果获取对象的内存地址,及字典的地址

    在python中,如果查看一个对象的内存地址,可以用到id这个内置函数:使用方式是: id(object)--->返回该对象的10进制的内存地址: 以下是官方定义:翻译为大白话就是,返回一个对象 ...

  2. 关键aspNetCore processPath 这一行,耗费了一天

    <?xml version="1.0" encoding="UTF-8"?> <configuration>   <locatio ...

  3. 批量修改excel中超链接

    打开需要处理的excel文件 alt + F11打开VB编辑器 双击打开对应的sheet 编辑如下代码 Dim oldfile As String Dim Newfile As String Sub ...

  4. Java 查找Panel 里的某个组件 比如 按钮

    遇到到一个需求,需要获取界面里的一个按钮,但是这个按钮是封装的父类嵌入的,知道label 的值. 写了一个递归获取它 1 private JButton LookupTheButton(Compone ...

  5. python之路3:文件操作和函数基础

    文件操作 字符编码解码 函数基础 内置函数 一.文件操作 对文件操作流程 打开文件,得到文件句柄并赋值给一个变量 通过句柄对文件进行操作 关闭文件 打开文件的模式有: r,只读模式(默认). w,只写 ...

  6. 通过抓取pintpoint2的页面信息把数据存入数据库python3

    目标:对生产环境的服务质量进行量化, 解决办法:把pintpoint2里的数据转存入mysql数据库,作成报表,目前支持总请求数,错误请求数,中位数,平均数,95值(每分钟一次定时任务),其它指标可以 ...

  7. Qt 一键部署脚本

    echo "begin deploying..." echo Setting up environment for Qt usage... set PATH=C:\Qt\Qt5.8 ...

  8. SpringBoot(十五)单个以及多个跨域的配置方法

    同源策略是浏览器的一个安全限制,要求域名.协议.端口相同,如果不同则没办法进行数据交互.而跨域配置,则是为了解除这方面的限制.前后端分离的情况下,因为需要分开部署,后台开发基本都需要进行跨域配置了.( ...

  9. zerotier的planet服务器(根服务器)-搭建教程

    应用场景介绍: 利用阿里云服务器,搭建根服务器,把不同局域网打通,实现内网穿透,远程控制. 准备工具:  1.服务端:云服务器(有公网IP)Centos 7.6 2.客户端:   工控机(或者家里电脑 ...

  10. Python——01.环境及安装

    Python介绍 -- Python是解释型,面向对象的语言,程序结构简洁,清晰 -- Python解释器分类: CPython(官方解释器):用C语言编写的Python解释器 PyPy:用Pytho ...