官方文档: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. demo4j解析xml

    1//先加入dom4j.jar包 2import java.util.HashMap; 3import java.util.Iterator; 4import java.util.Map; 5 6im ...

  2. Django+Ajax+Mysql实现数据库数据的展示

    最近老师让搞一个系统,仅仅展示一下数据库的数据 在做海底捞时,是交接的师兄的项目,用的语言是java,框架是SSM(Spring.SpringMVC.MyBatis),这次我准备用Python写,前端 ...

  3. idea 创建项目没有web.xml文件,如何添加

    1.首先看下项目工程里面是否有WEB-INF文件夹,没有就创建一个 2.点击 file 选择 project structure 3.选择 facets,点击+号, 选择 web 4.弹出 弹框 选择 ...

  4. ReactJS - 组件的生命周期

    组件的生命周期分为三个状态 Mounting: 已插入真实DOM Updateing: 正在被重新渲染 Unmounting: 已移出真实DOM React 为每个状态都提供了两种处理函数,即函数在进 ...

  5. Android USB应用开发指南

    调试 USB接口被占用后使用wifi调试模式 详见:https://blog.csdn.net/u013758456/article/details/78911812 开发

  6. RabbitMQ传输原理、五种模式

    本文代码基于SpringBoot,文末有代码连接 .首先是一些在Spring Boot的一些配置和概念,然后跟随代码看下五种模式 MQ两种消息传输方式,点对点(代码中的简单传递模式),发布/订阅(代码 ...

  7. cxf整合spring代码

    导入jar包cxf的jar包 创建实体类 package com.yhd.webservice.cxf.server.poto; public class Person { private Strin ...

  8. 2015-09-23-Archlinux的一些配置

    firefox的flash插件 pacman -S flashplugin firefox上网慢 由于Chromium浏览器,打字的时候经常会跳字母,所以就换了firefox浏览器,但是FF上网的时候 ...

  9. Java开发面试常见问题合集

    次面试事故 面试官:你看过哪些源码?我:都挺熟悉的面试官:对hashMap了解程度怎么样?面试官:那你能讲讲 HashMap的实现原理吗?面试官:HashMap什么时候会进行 rehash?面试官:结 ...

  10. python--防止SQL注入

    from pymysql import * def main(): # 创建Connextion连接 conn = connect(host='localhost', port=3306, user= ...