GuavaCache简介(一)
原文地址 http://blog.csdn.net/guozebo/article/details/51590517
前言
在多线程高并发场景中往往是离不开cache的,需要根据不同的应用场景来需要选择不同的cache,比如分布式缓存如redis、memcached,还有本地(进程内)缓存如ehcache、GuavaCache。之前用spring cache的时候集成的是ehcache,但接触到GuavaCache之后,被它的简单、强大、及轻量级所吸引。它不需要配置文件,使用起来和ConcurrentHashMap一样简单,而且能覆盖绝大多数使用cache的场景需求!
GuavaCache是google开源java类库Guava的其中一个模块,在maven工程下使用可在pom文件加入如下依赖:
- <dependency>
- <groupId>com.google.guava</groupId>
- <artifactId>guava</artifactId>
- <version>19.0</version>
- </dependency>
Cache接口及其实现
先说说一般的cache都会实现的基础功能包括:
提供一个存储缓存的容器,该容器实现了存放(Put)和读取(Get)缓存的接口供外部调用。 缓存通常以<key,value>的形式存在,通过key来从缓存中获取value。当然容器的大小往往是有限的(受限于内存大小),需要为它设置清除缓存的策略。
在GuavaCache中缓存的容器被定义为接口Cache<K, V>的实现类,这些实现类都是线程安全的,因此通常定义为一个单例。并且接口Cache是泛型,很好的支持了不同类型的key和value。作为示例,我们构建一个key为Integer、value为String的Cache实例:
- final static Cache<Integer, String> cache = CacheBuilder.newBuilder()
- //设置cache的初始大小为10,要合理设置该值
- .initialCapacity(10)
- //设置并发数为5,即同一时间最多只能有5个线程往cache执行写入操作
- .concurrencyLevel(5)
- //设置cache中的数据在写入之后的存活时间为10秒
- .expireAfterWrite(10, TimeUnit.SECONDS)
- //构建cache实例
- .build();
据说GuavaCache的实现是基于ConcurrentHashMap的,因此上面的构造过程所调用的方法,通过查看其官方文档也能看到一些类似的原理。比如通过initialCapacity(5)定义初始值大小,要是定义太大就好浪费内存空间,要是太小,需要扩容的时候就会像map一样需要resize,这个过程会产生大量需要gc的对象,还有比如通过concurrencyLevel(5)来限制写入操作的并发数,这和ConcurrentHashMap的锁机制也是类似的(ConcurrentHashMap读不需要加锁,写入需要加锁,每个segment都有一个锁)。
接下来看看Cache提供哪些方法(只列了部分常用的):
- /**
- * 该接口的实现被认为是线程安全的,即可在多线程中调用
- * 通过被定义单例使用
- */
- public interface Cache<K, V> {
- /**
- * 通过key获取缓存中的value,若不存在直接返回null
- */
- V getIfPresent(Object key);
- /**
- * 通过key获取缓存中的value,若不存在就通过valueLoader来加载该value
- * 整个过程为 "if cached, return; otherwise create, cache and return"
- * 注意valueLoader要么返回非null值,要么抛出异常,绝对不能返回null
- */
- V get(K key, Callable<? extends V> valueLoader) throws ExecutionException;
- /**
- * 添加缓存,若key存在,就覆盖旧值
- */
- void put(K key, V value);
- /**
- * 删除该key关联的缓存
- */
- void invalidate(Object key);
- /**
- * 删除所有缓存
- */
- void invalidateAll();
- /**
- * 执行一些维护操作,包括清理缓存
- */
- void cleanUp();
- }
使用过程还是要认真查看官方的文档,以下Demo简单的展示了Cache的写入,读取,和过期清除策略是否生效:
- public static void main(String[] args) throws Exception {
- cache.put(1, "Hi");
- for(int i=0 ;i<100 ;i++) {
- SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
- System.out.println(sdf.format(new Date())
- + " key:1 ,value:"+cache.getIfPresent(1));
- Thread.sleep(1000);
- }
- }
清除缓存的策略
基于存活时间的清除(Timed Eviction)
这应该是最常用的清除策略,在构建Cache实例的时候,CacheBuilder提供两种基于存活时间的构建方法:
基于容量的清除(size-based eviction)
显式清除
(1)个别清除:Cache.invalidate(key)
(2)批量清除:Cache.invalidateAll(keys)
(3)清除所有缓存项:Cache.invalidateAll()
基于引用的清除(Reference-based Eviction)
在构建Cache实例过程中,通过设置使用弱引用的键、或弱引用的值、或软引用的值,从而使JVM在GC时顺带实现缓存的清除,不过一般不轻易使用这个特性。
清除什么时候发生?
- public class CacheService {
- static Cache<Integer, String> cache = CacheBuilder.newBuilder()
- .expireAfterWrite(5, TimeUnit.SECONDS)
- .build();
- public static void main(String[] args) throws Exception {
- new Thread() { //monitor
- public void run() {
- while(true) {
- SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
- System.out.println(sdf.format(new Date()) +" size: "+cache.size());
- try {
- Thread.sleep(2000);
- } catch (InterruptedException e) {
- }
- }
- };
- }.start();
- SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
- cache.put(1, "Hi");
- System.out.println("write key:1 ,value:"+cache.getIfPresent(1));
- Thread.sleep(10000);
- // when write ,key:1 clear
- cache.put(2, "bbb");
- System.out.println("write key:2 ,value:"+cache.getIfPresent(2));
- Thread.sleep(10000);
- // when read other key ,key:2 do not clear
- System.out.println(sdf.format(new Date())
- +" after write, key:1 ,value:"+cache.getIfPresent(1));
- Thread.sleep(2000);
- // when read same key ,key:2 clear
- System.out.println(sdf.format(new Date())
- +" final, key:2 ,value:"+cache.getIfPresent(2));
- }
- }
- 00:34:17 size: 0
- write key:1 ,value:Hi
- 00:34:19 size: 1
- 00:34:21 size: 1
- 00:34:23 size: 1
- 00:34:25 size: 1
- write key:2 ,value:bbb
- 00:34:27 size: 1
- 00:34:29 size: 1
- 00:34:31 size: 1
- 00:34:33 size: 1
- 00:34:35 size: 1
- 00:34:37 after write, key:1 ,value:null
- 00:34:37 size: 1
- 00:34:39 final, key:2 ,value:null
- 00:34:39 size: 0
(3)发生读操作cache.getIfPresent(1)后,缓存项<2,"bbb">没有被清除,因为还是size=1,看来读操作确实不一定会发生清除
总结
参考
GuavaCache简介(一)的更多相关文章
- GuavaCache简介(一)是轻量级的框架 少量数据,并且 过期时间相同 可以用 GuavaCache
还有一篇文章是讲解redis 如何删除过期数据的,参考:Redis的内存回收策略和内存上限(阿里) 划重点:在GuavaCache中,并不存在任何线程!它实现机制是在写操作时顺带做少量的维护工作(如清 ...
- Guava Cache本地缓存
Guava介绍 Guava是一种基于开源的Java库,其中包含谷歌正在由他们很多项目使用的很多核心库. 这个库是为了方便编码,并减少编码错误. 这个库提供用于集合,缓存,支持原语,并发性,常见注解,字 ...
- Redis的内存回收策略和内存上限(阿里)
还有一篇文章 讲解guava如何删除过期数据的,与redis不同,guava没有维护线程删除过期key,只是在设置 key 或者 读取key的时候,顺带删除参考:GuavaCache简介(一)是轻量级 ...
- GuavaCache学习笔记三:底层源码阅读
申明:转载自 https://www.cnblogs.com/dennyzhangdd/p/8981982.html 感谢原博主的分享,看到这个写的真好,直接转载来,学习了. 另外也推荐另外一篇Gua ...
- ASP.NET Core 1.1 简介
ASP.NET Core 1.1 于2016年11月16日发布.这个版本包括许多伟大的新功能以及许多错误修复和一般的增强.这个版本包含了多个新的中间件组件.针对Windows的WebListener服 ...
- MVVM模式和在WPF中的实现(一)MVVM模式简介
MVVM模式解析和在WPF中的实现(一) MVVM模式简介 系列目录: MVVM模式解析和在WPF中的实现(一)MVVM模式简介 MVVM模式解析和在WPF中的实现(二)数据绑定 MVVM模式解析和在 ...
- Cassandra简介
在前面的一篇文章<图形数据库Neo4J简介>中,我们介绍了一种非常流行的图形数据库Neo4J的使用方法.而在本文中,我们将对另外一种类型的NoSQL数据库——Cassandra进行简单地介 ...
- REST简介
一说到REST,我想大家的第一反应就是“啊,就是那种前后台通信方式.”但是在要求详细讲述它所提出的各个约束,以及如何开始搭建REST服务时,却很少有人能够清晰地说出它到底是什么,需要遵守什么样的准则. ...
- Microservice架构模式简介
在2014年,Sam Newman,Martin Fowler在ThoughtWorks的一位同事,出版了一本新书<Building Microservices>.该书描述了如何按照Mic ...
随机推荐
- Java-API:javax.servlet.http.HttpServletResponse
ylbtech-Java-API:javax.servlet.http.HttpServletResponse 1.返回顶部 1. javax.servlet.http Interface HttpS ...
- CSS-MUI:笔记-01
ylbtech-CSS-MUI:笔记 1. mui-navbar 导航条返回顶部 1.1.样式一 1.2. <div class="mui-navbar-inner mui-bar ...
- Struts2中web.xml里面struts-cleanup作用
struts2.1.3之后的版本均不需要配置该过滤器 参考: struts-cleanup作用 升级到struts-2.3.14.3之后涉及的改动以及ActionContextCleanUp,Stru ...
- Oracle 12c 搭建学习
Oracle 12c 搭建学习 Vm workstaton10 安装linux 6.4 安装oracle12c Oracle 12c只支持64位系统 1 环境检查 [root@rac1 ~]# gre ...
- form(去掉关闭按钮,禁止调整大小)
禁止Form窗口调整大小方法:FormBorderStyle 设为FixedSingle: 不能使用最大化窗口: MaximuzeBox 设为False: 不能使用最小化窗口: MinimizeB ...
- Oracle merge into 语句进行insert或者update操作,如果存在就update,如果不存在就insert
merge into的形式: MERGE INTO [target-table] A USING [source-table sql] B ON([conditional expression] ...
- 关于stickybroadcast
stickybroadcast顾名思义,粘性广播,从字面上我们可以联想到service的返回值中也有个一stick,在service中stick作用是当返回了之后服务被杀死,会重启服务. 但是这里的s ...
- day17 13.滚动结果集介绍
滚动 一般结果集只能是向下的,不是滚动的,你要是想让它滚动你得设置才行. 类名或者接口里面有静态的可以.接口里面的属性全部都是public static final,类名/接口名.是属性,这些都是常量 ...
- LINUX中错误 SELinux is disabled
解决: setenforce: SELinux is disabled 那么说明selinux已经被彻底的关闭了 如果需要重新开启selinux,请按下面步骤: vi /etc/selinux/con ...
- POJ 2176 Folding(区间DP)
题意:给你一个字符串,请把字符串压缩的尽量短,并且输出最短的方案. 例如:AAAAA可压缩为5(A), NEERCYESYESYESNEERCYESYESYES可压缩为2(NEERC3(YES)). ...