Google Guava之--cache

一、简介
  Google Guava包含了Google的Java项目许多依赖的库,如:集合 [collections] 、缓存 [caching] 、原生类型支持 [primitives support] 、并发库 [concurrency libraries] 、通用注解 [common annotations] 、字符串处理 [string processing] 、I/O 等等。本文只介绍其中的缓存部分。
  Guava Cache是一种本地缓存实现,支持多种缓存过期策略。性能好,简单易用。缓存在很多场景下都是很有用的。如,通过key获取一个value的花费的时间很多,而且获取的次数不止一次的时候,就应该考虑使用缓存。Guava Cache与ConcurrentMap很相似,但也不完全一样。最基本的区别是ConcurrentMap会一直保存所有添加的元素,直到显式地移除。而Guava Cache为了限制内存占用,通常都设定为自动回收元素。在某些场景下,尽管LoadingCache 不回收元素,它也会自动加载缓存。

  Guava Cache适用于以下应用场景:

  • 系统的访问速度首要考虑,而内存空间为次要考虑。
  • 某些key对于的value会被查询多次。
  • 缓存中存放的数据总量不会超出内存的全部大小。

本文例子使用的guava 版本为guava-18.0.jar,下载地址如下:
http://central.maven.org/maven2/com/google/guava/guava/18.0/guava-18.0.jar

二、Cache使用方式

  1、CacheLoader方式

  代码如下:

 1 import java.util.ArrayList;
 2 import java.util.List;
 3 import java.util.concurrent.ExecutionException;
 4 import java.util.concurrent.TimeUnit;
 5
 6 import org.junit.Test;
 7
 8 import com.google.cacahe.Person;
 9 import com.google.common.cache.CacheBuilder;
10 import com.google.common.cache.CacheLoader;
11 import com.google.common.cache.LoadingCache;
12
13 public class TestGuavaCache {
14
15     @Test
16     public void testUserCacheLoader() throws ExecutionException {
17         // 模拟数据
18         final List<Person> list = new ArrayList<Person>(5);
19         list.add(new Person("1", "zhangsan"));
20         list.add(new Person("2", "lisi"));
21         list.add(new Person("3", "wangwu"));
22
23         // 创建cache
24         LoadingCache<String, Person> cache = CacheBuilder.newBuilder()//
25                 .refreshAfterWrite(1, TimeUnit.MINUTES)// 给定时间内没有被读/写访问,则回收。
26                 // .expireAfterWrite(5, TimeUnit.SECONDS)//给定时间内没有写访问,则回收。
27                 // .expireAfterAccess(3, TimeUnit.SECONDS)// 缓存过期时间为3秒
28                 .maximumSize(100).// 设置缓存个数
29                 build(new CacheLoader<String, Person>() {
30                     @Override
31                     /**  当本地缓存命没有中时,调用load方法获取结果并将结果缓存
32                      */
33                     public Person load(String key) throws ExecutionException {
34                         System.out.println(key + " load in cache");
35                         return getPerson(key);
36                     }
37
38                     // 此时一般我们会进行相关处理,如到数据库去查询
39                     private Person getPerson(String key) throws ExecutionException {
40                         System.out.println(key + " query");
41                         for (Person p : list) {
42                             if (p.getId().equals(key))
43                                 return p;
44                         }
45                         return null;
46                     }
47                 });
48
49         cache.get("1");
50         cache.get("2");
51         cache.get("3");
52         System.out.println("======= sencond time  ==========");
53         cache.get("1");
54         cache.get("2");
55         cache.get("3");
56     }
57 }

  执行结果如下:

1 load in cache
1 query
2 load in cache
2 query
3 load in cache
3 query
======= sencond time  ==========

  第二次获取的时候没有执行获取的方法,而是直接从缓存中获取。

  2、Callback方式

  代码如下:

 1 import java.util.ArrayList;
 2 import java.util.List;
 3 import java.util.concurrent.Callable;
 4 import java.util.concurrent.ExecutionException;
 5
 6 import org.junit.Test;
 7
 8 import com.google.cacahe.Person;
 9 import com.google.common.cache.Cache;
10 import com.google.common.cache.CacheBuilder;
11
12 public class TestGuavaCache {
13
14
15     @Test
16     public void testUserCallback() throws ExecutionException {
17         // 模拟数据
18         final List<Person> list = new ArrayList<Person>(5);
19         list.add(new Person("1", "zhangsan"));
20         list.add(new Person("2", "lisi"));
21         list.add(new Person("3", "wangwu"));
22
23         final String key = "1";
24         Cache<String, Person> cache2 = CacheBuilder.newBuilder().maximumSize(1000).build();
25         /**
26          * 用缓存中的get方法,当缓存命中时直接返回结果;否则,通过给定的Callable类call方法获取结果并将结果缓存。<br/>
27          * 可以用一个cache对象缓存多种不同的数据,只需创建不同的Callable对象即可。
28          */
29         Person person = cache2.get(key, new Callable<Person>() {
30             public Person call() throws ExecutionException {
31                 System.out.println(key + " load in cache");
32                 return getPerson(key);
33             }
34
35             // 此时一般我们会进行相关处理,如到数据库去查询
36             private Person getPerson(String key) throws ExecutionException {
37                 System.out.println(key + " query");
38                 for (Person p : list) {
39                     if (p.getId().equals(key))
40                         return p;
41                 }
42                 return null;
43             }
44         });
45         System.out.println("======= sencond time  ==========");
46         person = cache2.getIfPresent(key);
47         person = cache2.getIfPresent(key);
48     }
49 }

  执行结果如下:

1 load in cache
1 query
======= sencond time  ==========

  第二次获取后也是直接从缓存中加载。

  3、关于移除监听器

  通过CacheBuilder.removalListener(RemovalListener),我们可以声明一个监听器,从而可以在缓存被移除时做一些其他的操作。当缓存被移除时,RemovalListener会获取移除bing通知[RemovalNotification],其中包含移除的key、value和RemovalCause。

  示例代码如下:

 1 import java.util.concurrent.ExecutionException;
 2 import java.util.concurrent.TimeUnit;
 3
 4 import org.junit.Test;
 5
 6 import com.google.cacahe.Person;
 7 import com.google.common.cache.CacheBuilder;
 8 import com.google.common.cache.CacheLoader;
 9 import com.google.common.cache.LoadingCache;
10 import com.google.common.cache.RemovalListener;
11 import com.google.common.cache.RemovalNotification;
12
13 public class TestGuavaCache {
14     @Test
15     public void testListener() throws ExecutionException {
16         CacheLoader<String, Person> loader = new CacheLoader<String, Person>() {
17             @Override
18             // 当本地缓存命没有中时,调用load方法获取结果并将结果缓存
19             public Person load(String key) throws ExecutionException {
20                 System.out.println(key + " load in cache");
21                 return getPerson(key);
22             }
23             // 此时一般我们会进行相关处理,如到数据库去查询
24             private Person getPerson(String key) throws ExecutionException {
25                 System.out.println(key + " query");
26                 return new Person(key, "zhang" + key);
27             }
28         };
29
30         // remove listener
31         RemovalListener<String, Person> removalListener = new RemovalListener<String, Person>() {
32             public void onRemoval(RemovalNotification<String, Person> removal) {
33                 System.out.println("cause:" + removal.getCause() + " key:" + removal.getKey() + " value:"
34                         + removal.getValue());
35             }
36         };
37
38         LoadingCache<String, Person> cache = CacheBuilder.newBuilder()//
39                 .expireAfterWrite(2, TimeUnit.MINUTES).maximumSize(1024).removalListener(removalListener).build(loader);
40         cache.get("1");// 放入缓存
41         cache.get("1");// 第二次获取(此时从缓存中获取)
42         cache.invalidate("1");// 移除缓存
43         cache.get("1");// 重新获取
44         cache.get("1");// 再次获取(此时从缓存中获取)
45     }
46 }

  运行结果如下:

1 1 load in cache
2 1 query
3 cause:EXPLICIT key:1 value:Person [id=1, name=zhang1]
4 1 load in cache
5 1 query

三、其他相关方法

  显式插入:该方法可以直接向缓存中插入值,如果缓存中有相同key则之前的会被覆盖。

cache.put(key, value);

  显式清除:我们也可以对缓存进行手动清除。

cache.invalidate(key); //单个清除
cache.invalidateAll(keys); //批量清除
cache.invalidateAll(); //清除所有缓存项

  基于时间的移除:

expireAfterAccess(long, TimeUnit); 该键值对最后一次访问后超过指定时间再移除
expireAfterWrite(long, TimeUnit) ;该键值对被创建或值被替换后超过指定时间再移除

  基于大小的移除:指如果缓存的对象格式即将到达指定的大小,就会将不常用的键值对从cache中移除。

cacheBuilder.maximumSize(long)

   size是指cache中缓存的对象个数。当缓存的个数开始接近size的时候系统就会进行移除的操作

  缓存清除执行的时间

  使用CacheBuilder构建的缓存不会"自动"执行清理和回收工作,也不会在某个缓存项过期后马上清理,也没有诸如此类的清理机制。它是在写操作时顺带做少量的维护工作(清理);如果写操作太少,读操作的时候也会进行少量维护工作。因为如果要自动地持续清理缓存,就必须有一个线程,这个线程会和用户操作竞争共享锁。在某些环境下线程创建可能受限制,这样CacheBuilder就不可用了。

时间: 2024-11-10 07:50:51

Google Guava之--cache的相关文章

使用google guava做内存缓存

google guava中有cache包,此包提供内存缓存功能.内存缓存需要考虑很多问题,包括并发问题,缓存失效机制,内存不够用时缓存释放,缓存的命中率,缓存的移除等等. 当然这些东西guava都考虑到了. guava中使用缓存需要先声明一个CacheBuilder对象,并设置缓存的相关参数,然后调用其build方法获得一个Cache接口的实例.请看下面的代码和注释,注意在注释中指定了Cache的各个参数. public static void main(String[] args) throw

google guava cache

老规矩,有些知识很容易忘记啊,还是记录一下咯. google guava cache中,有很多参数. 1.expireAfterAccess(n , timeunit)   表示cache中管理的key如果在n(s,m,h,d)时间范围内没有被使用,则被cache驱逐. 2.maximumSize(n)   表示可以缓存的最大数目.没有到达最大数目时, 即开始驱逐部门缓存数据. 3.removalListener     实现RemovalListener接口onRemoval方法.可以记录缓存

(翻译)Google Guava Cache

翻译自Google Guava Cache This Post is a continuation of my series on Google Guava, this time covering Guava Cache. Guava Cache offers more flexibility and power than either a HashMap or ConcurrentHashMap, but is not as heavy as using EHCache or Memcache

Google Guava教程

Google Guava官方教程(中文版) 原文链接  译文链接 译者: 沈义扬,罗立树,何一昕,武祖  校对:方腾飞 引言 Guava工程包含了若干被Google的 Java项目广泛依赖 的核心库,例如:集合 [collections] .缓存 [caching] .原生类型支持 [primitives support] .并发库 [concurrency libraries] .通用注解 [common annotations] .字符串处理 [string processing] .I/O

Guava学习笔记:Google Guava 类库简介

> Guava 是一个 Google 的基于java1.6的类库集合的扩展项目,包括 collections, caching, primitives support, concurrency libraries, common annotations, string processing, I/O, 等等. 这些高质量的 API 可以使你的JAVa代码更加优雅,更加简洁,让你工作更加轻松愉悦.下面我们就开启优雅Java编程学习之旅! 项目相关信息: 官方首页:http://code.googl

Google Guava简介

Guava工程包含了若干被Google的 Java项目广泛依赖 的核心库,例如:集合(collections).缓存(caching).原生类型支持(primitives support).并发库 (concurrency libraries).通用注解(common annotations).字符串处理(string processing).I/O 等等. 所有这些工具每天都在被Google的工程师应用在产品服务中. 项目信息 首页:https://code.google.com/p/guav

Google Guava入门教程

以下资料整理自网络 一.Google Guava入门介绍 引言 Guava工程包含了若干被Google的 Java项目广泛依赖 的核心库,例如:集合 [collections] .缓存 [caching] .原生类型支持 [primitives support] .并发库 [concurrency libraries] .通用注解 [common annotations] .字符串处理 [string processing] .I/O 等等. 所有这些工具每天都在被Google的工程师应用在产品

Google Guava 类库简介

Guava 是一个 Google开发的 基于java的类库集合的扩展项目,包括 collections, caching, primitives support, concurrency libraries, common annotations, string processing, I/O, 等等. 这些高质量的 API 可以使你的JAVA代码更加优雅,更加简洁,让你工作更加轻松愉悦.下面我们就简单的介绍一下Guava的大致的功能! Guava项目托管在github上,可以使用sudo gi

Java内存缓存-通过Google Guava创建缓存

谷歌Guava缓存 Guava介绍 Guava是Google guava中的一个内存缓存模块,用于将数据缓存到JVM内存中.实际项目开发中经常将一些公共或者常用的数据缓存起来方便快速访问. Guava Cache是单个应用运行时的本地缓存.它不把数据存放到文件或外部服务器.如果不符合需求,可以选择Memcached.Redis等工具. 小案例 pom.xml添加guava依赖 <?xml version="1.0" encoding="UTF-8"?>