GUAVA  Cache

Guava Cache与ConcurrentMap很相似基于分段锁及线程安全,但也不完全一样。最基本的区别是ConcurrentMap会一直保存所有添加的元素,直到显式地移除。相对地,Guava Cache为了限制内存占用,通常都设定为自动回收元素。在某些场景下,尽管LoadingCache 不回收元素,它也是很有用的,因为它会自动加载缓存。

适用场景

1)可以接受消耗内存来提高性能

2)某些key会被多次查询

3)缓存中的数据量不会超出内存容量

使用案例

package com.guava.cache;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable; import org.junit.Test; import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.google.common.collect.Lists;
/**
*
* @author gaojiayi
*
*/
public class TestCache {
//基于loadingCache加载
//@Test
public void TestLoadingCache() throws Exception{
LoadingCache<String,String> cahceBuilder=CacheBuilder
.newBuilder()
.build(new CacheLoader<String, String>(){
//提供默认的加载加载方式,在实际生产中,可以选择从DB中,或者文件中加载相应的value
@Override
public String load(String key) throws Exception {
String strProValue="hello "+key+"!";
return strProValue;
}
//批量加载
@Override
public Map<String, String> loadAll(Iterable<? extends String> keys) throws Exception {
// TODO Auto-generated method stub
Map<String, String> retMap = new HashMap<String, String>();
for(String key: keys){
retMap.put(key, load(key));
}
return retMap;
} }); System.out.println("jerry value:"+cahceBuilder.apply("jerry"));
//get(K)方法,这个方法要么返回已经缓存的值,要么使用CacheLoader向缓存原子地加载新值。
System.out.println("jerry value:"+cahceBuilder.get("jerry"));
System.out.println("peida value:"+cahceBuilder.get("peida"));
System.out.println("peida value:"+cahceBuilder.apply("peida"));
System.out.println("lisa value:"+cahceBuilder.apply("lisa"));
//使用cache.put(key, value)方法可以直接向缓存中插入值,这会直接覆盖掉给定键之前映射的值
cahceBuilder.put("harry", "ssdded");
System.out.println("harry value:"+cahceBuilder.get("harry")); System.out.println("________________________________________");
List<String> list = new ArrayList<>();
list.add("1");
list.add("2");
System.out.println(cahceBuilder.getAll(list));
} //基于Callable加载
@Test
public void testcallableCache()throws Exception{
Cache<String, String> cache = CacheBuilder.newBuilder().maximumSize(1000).build();
String resultVal = cache.get("jerry", new Callable<String>() {
public String call() {
String strProValue="hello "+"jerry"+"!";
return strProValue;
}
});
System.out.println("jerry value : " + resultVal); resultVal = cache.get("peida", new Callable<String>() {
public String call() {
String strProValue="hello "+"peida"+"!";
return strProValue;
}
});
System.out.println("peida value : " + resultVal);
}
}

缓存回收

使用CacheBuilder构建的缓存不会"自动"执行清理和回收工作,也不会在某个缓存项过期后马上清理,也没有诸如此类的清理机制。相反,它会在写操作时顺带做少量的维护工作,或者偶尔在读操作时做——如果写操作实在太少的话。

这样做的原因在于:如果要自动地持续清理缓存,就必须有一个线程,这个线程会和用户操作竞争共享锁。此外,某些环境下线程创建可能受限制,这样CacheBuilder就不可用了。

相反,我们把选择权交到你手里。如果你的缓存是高吞吐的,那就无需担心缓存的维护和清理等工作。如果你的 缓存只会偶尔有写操作,而你又不想清理工作阻碍了读操作,那么可以创建自己的维护线程,以固定的时间间隔调用Cache.cleanUp()ScheduledExecutorService可以帮助你很好地实现这样的定时调度。

基于容量的回收

CacheBuilder.maximumSize(long)

基于权重回收

 //。在权重限定场景中,除了要注意回收也是在重量逼近限定值时就进行了,
//还要知道重量是在缓存创建时计算的,因此要考虑重量计算的复杂度。
Cache<String, String> cache = CacheBuilder.newBuilder().maximumSize(1000)
.maximumWeight(100)
.weigher(new Weigher<String,String>(){ @Override
public int weigh(String key, String value) {
// TODO Auto-generated method stub
return value.getBytes().length;
} }).build();

定时回收

  • expireAfterAccess(long, TimeUnit):缓存项在给定时间内没有被读/写访问,则回收。请注意这种缓存的回收顺序和基于大小回收一样。
  • expireAfterWrite(long, TimeUnit):缓存项在给定时间内没有被写访问(创建或覆盖),则回收。如果认为缓存数据总是在固定时候后变得陈旧不可用,这种回收方式是可取的。

基于引用的回收(Reference-based Eviction)

通过使用弱引用的键、或弱引用的值、或软引用的值,Guava Cache可以把缓存设置为允许垃圾回收:

  • CacheBuilder.weakKeys():使用弱引用存储键。当键没有其它(强或软)引用时,缓存项可以被垃圾回收。因为垃圾回收仅依赖恒等式(==),使用弱引用键的缓存用==而不是equals比较键。
  • CacheBuilder.weakValues():使用弱引用存储值。当值没有其它(强或软)引用时,缓存项可以被垃圾回收。因为垃圾回收仅依赖恒等式(==),使用弱引用值的缓存用==而不是equals比较值。
  • CacheBuilder.softValues():使用软引用存储值。软引用只有在响应内存需要时,才按照全局最近最少使用的顺序回收。考虑到使用软引用的性能影响,我们通常建议使用更有性能预测性的缓存大小限定(见上文,基于容量回收)。使用软引用值的缓存同样用==而不是equals比较值。

显式清除

任何时候,你都可以显式地清除缓存项,而不是等到它被回收:

刷新reload

      LoadingCache<String,String> cahceBuilder=CacheBuilder
.newBuilder()
//注意:缓存并不会因为刷新盲目地定时重置,如果缓存项没有被检索,那刷新就不会真的发生,
//(可以理解未异步定时获取新增,而不会做刷新,只有被检索时才会真正刷新)
//如果设置过期(expireAfterWrite)缓存项在过期时间后也变得可以回收。
.refreshAfterWrite(2, TimeUnit.MINUTES)
.build(new CacheLoader<String, String>(){
//提供默认的加载加载方式,在实际生产中,可以选择从DB中,或者文件中加载相应的value
@Override
public String load(String key) throws Exception {
String strProValue="hello "+key+"!";
return strProValue;
}
//重新加载:重载CacheLoader.reload(K, V)可以扩展刷新时的行为,这个方法允许开发者在计算新值时使用旧的值。
@Override
public ListenableFuture<String> reload(String key, String oldValue) throws Exception {
// TODO Auto-generated method stub
return super.reload(key, oldValue);
} });

删除操作监听

 Cache<String, String> cache = CacheBuilder.newBuilder().maximumSize(1000)
.removalListener(new RemovalListener<String,String>(){ @Override
public void onRemoval(RemovalNotification<String, String> removalnotification) {
// 释放资源 }})

参考:http://www.cnblogs.com/peida/p/Guava_Cache.html

GUAVA-cache实现的更多相关文章

  1. Spring cache简单使用guava cache

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

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

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

  3. Guava学习笔记:Guava cache

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

  4. Ehcache与Guava Cache的区别浅谈

    最近在做一些缓存改造的场景,有如下一些经验总结: 缓存版本: Ehcache:2.8.3 Guava:17.0 Ehcache支持持久化到本地磁盘,Guava不可以: Ehcache有现成的集群解决方 ...

  5. guava cache

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

  6. 第七章 企业项目开发--本地缓存guava cache

    1.在实际项目开发中,会使用到很多缓存技术,而且数据库的设计一般也会依赖于有缓存的情况下设计. 常用的缓存分两种:本地缓存和分布式缓存. 常用的本地缓存是guava cache,本章主要介绍guava ...

  7. (翻译)Google Guava Cache

    翻译自Google Guava Cache This Post is a continuation of my series on Google Guava, this time covering G ...

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

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

  9. Guava Cache源码解析

    概述: 本次主要是分析cache的源码,基本概念官方简介即可. 基本类图: 在官方的文档说明中,Guava Cache实现了三种加载缓存的方式: LoadingCache在构建缓存的时候,使用buil ...

  10. google guava cache缓存基本使用讲解

    代码地址:https://github.com/vikde/demo-guava-cache 一.简介 guava cache是google guava中的一个内存缓存模块,用于将数据缓存到JVM内存 ...

随机推荐

  1. [jvm] -- 内存模型篇

    内存模型 JDK1.6  JDK1.8  线程私有的: 程序计数器 虚拟机栈 本地方法栈 线程共享的: 堆 方法区 直接内存 (非运行时数据区的一部分) 程序计数器 线程私有 两个作用 字节码解释器通 ...

  2. vue使用select间相互绑定

    让这两个select相互绑定,让roleOptions选取值后,worklist弹出得是roleOptions值 <el-select v-model="postForm.projec ...

  3. python爬虫入门(1)----- requests

    介绍 requests是python实现的简单易用的HTTP库,使用起来比urllib简洁很多 基本使用 requests.get("http://www.baidu.com") ...

  4. django-rest-framework-源码解析001-整体框架

    简介 Django Rest Framework是一个强大且灵活的工具包,主要用以构建RESTful风格的Web API. Django REST Framework(简称DRF)可以在Django的 ...

  5. dp最长不下降序列

    // // Created by snnnow on 2020/4/13. // //这是dp 问题的基础题 // //最长不下降 //(导弹拦截是其例题) //那这篇文章是讲啥呢, // 主要是吧, ...

  6. Python元组内置函数

    Python元组内置函数: len(元组名): 返回元组长度 # len(元组名): # 返回元组长度 tuple_1 = (1,2,3,'a','b','c') print("tuple_ ...

  7. The JOIN operation -- SQLZOO

    The JOIN operation 注意:where语句中对表示条件的需要用单引号, 下面的译文使用的是有道翻译如有不正确,请直接投诉有道 01.Modify it to show the matc ...

  8. PHP substr_replace() 函数

    实例 把 "Hello" 替换成 "world": <?php高佣联盟 www.cgewang.comecho substr_replace(" ...

  9. java中的枚举类enum

    enum SeasonEnum {//枚举类: 本类规定了SeasonEnum(季节)类只能有四个对象SPRING,SUMMER,AUMUTN,WINTER //创建枚举类的的四个对象SPRING,S ...

  10. SpringBoot学习之整合Mybatis

    本博客使用IDEA开发工具,通过Maven构建SpringBoot项目,初始化项目添加的依赖有:spring-boot-starter-jdbc.spring-boot-starter-web.mys ...