官方文档:https://github.com/google/guava/wiki/CachesExplained

目录

  一、guava cache介绍

  二、快速入门

    2.1、引入依赖

    2.2、第一个示例

    2.3、批量操作

  三、拓展

    3.1、移除监听器

    3.2、刷新缓存

    3.3、自定义刷新的操作

一、guava cache介绍

  对于常见的cache(缓存),比如memecache、redis、tair这些中间件,也有jdk的一些类库可以当做缓存使用,比如实现了ConcurrentMap接口的ConcurrentHashMap。

  ConcurrentHashMap虽然可以让我们在程序中缓存一些数据,但是这些数据其实永远不会过期,除非手动删除,否则数据将一直存在于内存中。

  而guava cache(LocalCache,本地缓存),也是实现了ConcurrentMap的类,但他和ConcurrentHashMap的区别在于,guava cache可以设置数据过期以及淘汰机制,更加符合一般的应用需求。

  guava cache,是一个本地缓存,也就是说,他的数据是存放在机器内存,这个机器,就是JVM所在的机器(会占用一部分内存),而不是像redis那样专门做缓存的机器。

二、快速入门

2.1、引入依赖

  guava cahce是guava的子模块。

  guava仓库地址:https://mvnrepository.com/artifact/com.google.guava/guava

<!-- https://mvnrepository.com/artifact/com.google.guava/guava -->
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>28.0-jre</version>
</dependency>

  

2.2、第一个示例

  下面是一个简单的示例:

package cn.ganlixin.guava;

import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import org.junit.Test; import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit; public class UseCache { @Test
public void testLoadingCache() throws ExecutionException {
// 创建缓存(容器)
LoadingCache<String, String> cache = CacheBuilder.newBuilder()
// 数据写入1分钟后失效
.expireAfterWrite(1, TimeUnit.MINUTES)
// 支持缓存项的数据最大为3个
.maximumSize(3)
// 实现CacheLoader,当在缓存中未找到所需的缓存项时,会执行CacheLoader的load方法加载缓存。
.build(new CacheLoader<String, String>() {
// 方法的返回值会被缓存,注意,返回null时,会抛异常
@Override
public String load(String key) throws Exception {
System.out.println("key:" + key + " 未找到,开始加载....");
return key + "-" + key;
}
}); // 加入缓存
cache.put("Java", "spring");
cache.put("PHP", "swoole"); // 从缓存中获取值
String res1 = cache.get("Java"); // get方法需要抛出ExecutionException异常
// cache.getUnchecked("Java"); // 功能和get一样,但是不会throw异常
System.out.println(res1);
// 输出:spring // 缓存中为存放key为Golang的缓存项,所以进行加载
String res2 = cache.get("Golang");
System.out.println(res2);
// key:Golang 未找到,开始加载....
// Golang-Golang // Golang的缓存项前面已经加载过了,且没有被清除,所以这次直接获取到对应的value
String res3 = cache.get("Golang");
System.out.println(res3);
// Golang-Golang // 前面添加了3个缓存项(已经达到设置上限,此时再添加缓存项,将会触发淘汰)
cache.put("Node", "KOA");
System.out.println(cache.get("PHP")); // PHP在cache中已被淘汰
// key:PHP 未找到,开始加载....
// PHP-PHP // 查询缓存,如果未找到,不会触发加载操作,而是范围null。
String res4 = cache.getIfPresent("key");
System.out.println(res4); // null
}
}  

  

2.3、批量操作

  guava cache支持批量添加、查询、清除操作。

package cn.ganlixin.guava;

import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.google.common.collect.ImmutableMap;
import org.junit.Test; import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit; public class UseCache { @Test
public void testMultiple() throws ExecutionException {
// 创建缓存
LoadingCache<String, String> loadingCache = CacheBuilder.newBuilder()
.maximumSize(2) // 最大缓存项数量为2
.expireAfterWrite(10, TimeUnit.SECONDS) // 数据写入10秒过期
.build(new CacheLoader<String, String>() {
@Override
public String load(String key) throws Exception {
System.out.println("key:" + key + " 未找到,开始加载....");
return key + "-" + key;
}
}); Map<String, String> map = new HashMap<>();
map.put("one", "111111");
map.put("two", "222222");
map.put("three", "3333333");
// 批量添加
loadingCache.putAll(map); List<String> keys = new ArrayList<>();
keys.add("one");
keys.add("two");
// 批量获取
ImmutableMap<String, String> allData = loadingCache.getAll(keys);
System.out.println(allData);
// {one=one-one, two=222222} // 批量清除
loadingCache.invalidateAll(keys);
loadingCache.invalidateAll(); // 全量清除
}
}

  

三、拓展

3.1、移除监听器

  移除监听器,是指监听缓存项,当缓存项被清除时,执行指定对操作。

package cn.ganlixin.guava;

import com.google.common.cache.*;
import org.junit.Test; import java.util.concurrent.TimeUnit; public class UseCache { @Test
public void testRemoveListender() { LoadingCache<String, String> cache = CacheBuilder.newBuilder()
.maximumSize(2)
.expireAfterWrite(1, TimeUnit.MINUTES)
// 绑定"移除监听器",当元素被清除时,执行onRemoval方法
.removalListener(new RemovalListener<String, String>() {
@Override
public void onRemoval(RemovalNotification removalNotification) {
Object key = removalNotification.getKey();
Object val = removalNotification.getValue();
System.out.println("被清除的元素,key:" + key + ", val:" + val); }
})
// 当在缓存中未找到key时,执行load操作。
.build(new CacheLoader<String, String>() {
// 当key未找到时,执行的加载操作
@Override
public String load(String key) throws Exception {
System.out.println("未找到key:" + key + ",开始加载...");
return key + key;
}
}); cache.put("one", "111111");
cache.put("two", "123456"); // 继续添加元素,会触发清理操作,触发移除监听器
cache.put("three", "2233333");
// 输出:被清除的元素,key:one, val:111111 String res = cache.getUnchecked("four");
System.out.println(res);
// 输出
// 未找到key:four,开始加载...
// 被清除的元素,key:two, val:123456
// fourfour
}
}

  

3.2、刷新缓存

  刷新缓存,是指一个缓存项写入缓存后,经过一段时间(设置的刷新间隔),再次访问该缓存项的时候,会刷新该缓存项,可以理解为将该项的key取出,执行CacheLoader的load方法,然后将返回值替换旧的值。

  可以在创建缓存的时候,设置刷新缓存的时间:

package cn.ganlixin.guava;

import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import org.junit.Test; import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit; public class UseCache { @Test
public void testRefresh() throws InterruptedException, ExecutionException {
LoadingCache<String, String> cache = CacheBuilder.newBuilder()
.maximumSize(2)
// 设置刷新的时机
.refreshAfterWrite(2, TimeUnit.SECONDS)
.build(new CacheLoader<String, String>() {
@Override
public String load(String key) throws Exception {
System.out.println("key:" + key + " 未找到,开始加载....");
return key + "-" + key;
}
}); cache.put("one", "11111");
cache.put("two", "22222"); // 休眠3秒
Thread.sleep(3000L); System.out.println(cache.get("one"));
//key:one 未找到,开始加载....
//one-one System.out.println(cache.get("two"));
//key:two 未找到,开始加载....
//two-two
}
}

  需要注意的是,以上面代码为例,并不是设置写入2秒后,就会被刷新,而是当写入2秒后,且再次被访问时,才会被刷新;如果一个缓存项写入的时间超过2秒,但是一直没有访问该项,那么这一项是不会被刷新的。这与Memecache和Redis的原理类似。

  

3.3、自定义刷新缓存的操作

  前面内容中,提到可以使用设置refreshAfterWrite()设置数据写入多久后,再次被访问时,会被刷新,其实,我们可以对于刷新操作自定义,只需要重写CacheLoader的reload方法即可。

package cn.ganlixin.guava;

import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.google.common.util.concurrent.ListenableFuture;
import org.junit.Test; import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit; public class UseCache { @Test
public void testReload() throws InterruptedException {
LoadingCache<String, String> cache = CacheBuilder.newBuilder()
.maximumSize(2)
// 设置刷新的时机
.refreshAfterWrite(2, TimeUnit.SECONDS)
.build(new CacheLoader<String, String>() {
@Override
public String load(String key) throws Exception {
System.out.println("key:" + key + " 未找到,开始加载....");
return key + "-" + key;
} // 刷新缓存时,执行的操作
@Override
public ListenableFuture<String> reload(String key, String oldValue) throws Exception {
System.out.println("刷新缓存项,key:" + key + ", oldValue:" + oldValue);
return super.reload(key, oldValue);
}
}); cache.put("hello", "world");
Thread.sleep(3000L); System.out.println(cache.getUnchecked("hello"));
// 刷新缓存项,key:hello, oldValue:world
// key:hello 未找到,开始加载....
// hello-hello
}
}

  

 

学习使用Guava Cache的更多相关文章

  1. spring boot guava cache 缓存学习

    http://blog.csdn.net/hy245120020/article/details/78065676 ****************************************** ...

  2. Guava学习笔记:Guava cache

    缓存,在我们日常开发中是必不可少的一种解决性能问题的方法.简单的说,cache 就是为了提升系统性能而开辟的一块内存空间. 缓存的主要作用是暂时在内存中保存业务系统的数据处理结果,并且等待下次访问使用 ...

  3. guava cache学习

    Guava Cache与ConcurrentMap很相似,但也不完全一样.最基本的区别是ConcurrentMap会一直保存所有添加的元素,直到显式地移除.相对地,Guava Cache为了限制内存占 ...

  4. Spring cache简单使用guava cache

    Spring cache简单使用 前言 spring有一套和各种缓存的集成方式.类似于sl4j,你可以选择log框架实现,也一样可以实现缓存实现,比如ehcache,guava cache. [TOC ...

  5. 是什么让spring 5放弃了使用Guava Cache?

    一路走来,Spring社区从刚开始的核心模块一直发展到现在,最近Sping5也完成了M5的发布, 相信不久之后第一个RELEASE版本也会发布.里面有很多特性是和即将要发布的JAVA 9息息相关的.今 ...

  6. Guava Cache探索及spring项目整合GuavaCache实例

    背景 对于高频访问但是低频更新的数据我们一般会做缓存,尤其是在并发量比较高的业务里,原始的手段我们可以使用HashMap或者ConcurrentHashMap来存储. 这样没什么毛病,但是会面临一个问 ...

  7. Spring配置cache(concurrentHashMap,guava cache、redis实现)附源码

    在应用程序中,数据一般是存在数据库中(磁盘介质),对于某些被频繁访问的数据,如果每次都访问数据库,不仅涉及到网络io,还受到数据库查询的影响:而目前通常会将频繁使用,并且不经常改变的数据放入缓存中,从 ...

  8. Guava Cache详解

    适用性 缓存在很多场景下都是相当有用的.例如,计算或检索一个值的代价很高,并且对同样的输入需要不止一次获取值的时候,就应当考虑使用缓存 Guava Cache与ConcurrentMap很相似,但也不 ...

  9. [Java 缓存] Java Cache之 Guava Cache的简单应用.

    前言 今天第一次使用MarkDown的形式发博客. 准备记录一下自己对Guava Cache的认识及项目中的实际使用经验. 一: 什么是Guava Guava工程包含了若干被Google的 Java项 ...

随机推荐

  1. Vscode 下 PlantUML 插件的安装(windows and ubuntu)

    目录 Windows 下安装 JAVA 安装环境配置: 测试 Ubuntu 16.04 下安装 Windows 下安装 Vscode graphviz PlantUML JAVA(推荐长期稳定版本,官 ...

  2. 代码死循环导致cpu使用率过高

    1. top命令查看进程pid  27081 2. ps -mp pid -o THREAD,tid,time  (tid:31128) 3.printf “%x\n” number  #将tid转换 ...

  3. slqmap简单使用

    网址:-u 指定哪个参数:-p 需要登录用--cookie 获得所有数据库:--dbs 获得所有用户:--users 指定某个数据库:-D 显示所有表--tables 指定某个数据表:-T 显示列:- ...

  4. 关于vyos 防火墙配置

    VyOS是一个基于Debian的网络操作系统,是Vyatta的社区fork.Vyatta是博通的企业级的产品,通过这套系统,能在x86平台提供路由,防火墙和×××的功能. 这个系统提供了和其他诸如Ci ...

  5. URI和URL对比

    URL是Uniform Resoure Locator(统一资源定位器)的缩写.就是WWW页的地址. 其URL地址格式排列为:scheme://host:Port/path --Internet资源类 ...

  6. android高仿抖音、点餐界面、天气项目、自定义view指示、爬取美女图片等源码

    Android精选源码 一个爬取美女图片的app Android高仿抖音 android一个可以上拉下滑的Ui效果 android用shape方式实现样式源码 一款Android上的新浪微博第三方轻量 ...

  7. Spring Cloud Alibaba-MyShop-项目介绍

    本节视频 [视频]Spring Cloud Alibaba-MyShop-项目介绍 开发环境 操作系统:Windows 10 Enterprise 开发工具:Intellij IDEA 数据库:MyS ...

  8. linux查看端口号占用命令-top

    题记 对于top命令来说,基本是都是linux命令入门中,第一个使用的命令,在windows中电脑如果卡顿,回去任务栏中查看cpu和内存的使用情况.top命令实现的就是这个重要的功能. 在系统维护的过 ...

  9. 4 Values whose Sum is 0 (二分+排序)

    题目: The SUM problem can be formulated as follows: given four lists A, B, C, D of integer values, com ...

  10. Binder机制简析(三)

    注册Service Service组件运行在Server进程中,首先要将Service注册到Service Manager中,再启动一个Binder线程池来等待和处理Client的通信请求. 注册过程 ...