Google的Guava cache 应用

Guava Cache 创建
基本上可以通过两种方式来创建cache:

cacheLoader
callable callback


通过这两种方法创建的cache,和通常用map来缓存的做法比,不同在于,这两种方法都实现了一种逻辑——从缓存中取key X的值,如果该值已经缓存过了,则返回缓存中的值,如果没有缓存过,可以通过某个方法来获取这个值。

但不同的在于cacheloader的定义比较宽泛,是针对整个cache定义的,可以认为是统一的根据key值load value的方法。

而callable的方式较为灵活,允许你在get的时候指定。

下面是两种方法的例子:

首先是基于cacheloader的方法

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@Test
public void testCacheBuilder()  throws ExecutionException {
 
     LoadingCache<String, String> graphs = CacheBuilder.newBuilder()
         .maximumSize( 1000 )
         .build( new CacheLoader<String, String>() {
             public String load(String key) {
                 // 这里是key根据实际去取值的方法
                 return "value" ;
             }
         });
 
     String resultVal = graphs.get( "testKey" );
     System.out.println(resultVal);
}


 其次是基于实现callable的方法:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@Test
public void testCallable()  throws ExecutionException {
     // 没有使用CacheLoader
     Cache<String, String> cache = CacheBuilder.newBuilder()
         .maximumSize( 1000 )
         .build();
 
     String resultVal = cache.get( "testKey" new Callable<String>() {
         public String call() {
             // 这里先根据key实际去取值的方法
             return "value" ;
         }
     });
     System.out.println(resultVal);
}

Guava Cache 数据的移除
被动移除数据的方式,guava默认提供了三种方式:


基于大小的移除

看字面意思就知道就是按照缓存的大小来移除,如果即将到达指定的大小,那就会把不常用的键值对从cache中移除。

定义的方式一般为 CacheBuilder.maximumSize(long),官方还介绍了一种可以算权重的方法,个人认为实际使用中不太用到,暂不讨论。

就这个常用的来看有几个注意点,
其一,这个size指的是cache中的条目数,不是内存大小或是其他;
其二,并不是完全到了指定的size系统才开始移除不常用的数据的,而是接近这个size的时候系统就会开始做移除的动作;
其三,如果一个键值对已经从缓存中被移除了,你再次请求访问的时候,如果cachebuild是使用cacheloader方式的,那依然还是会从cacheloader中再取一次值,如果这样还没有,就会抛出异常


基于时间的移除

      guava提供了两个基于时间移除的方法
      expireAfterAccess(long, TimeUnit)  这个方法是根据某个键值对最后一次访问之后多少时间后移除
      expireAfterWrite(long, TimeUnit)    这个方法是根据某个键值对被创建或值被替换后多少时间移除

基于引用的移除

      这种移除方式主要是基于java的垃圾回收机制,根据键或者值的引用关系决定移除,个人对垃圾回收这块不是非常了解,窃以为不太可靠。。也不常用。。所以没有研究,欢迎补充。


主动移除数据方式 
       主动移除有三种方法: 
             单独移除用 Cache.invalidate(key)
     批量移除用 Cache.invalidateAll(keys)
             移除所有用 Cache.invalidateAll()


       如果需要在移除数据的时候有所动作还可以定义Removal Listener,但是有点需要注意的是默认Removal Listener中的行为是和移除动作同步执行的,如果需要改成异步形式,可以考虑使用RemovalListeners.asynchronous(RemovalListener, Executor)

Guava Cache 的清空,刷新及统计功能
主要介绍guava cache的清空,刷新和统计的功能。 
缓存数据的清空 
      guava没有提供自动触发清空缓存数据的功能,而是提供了一种手工调用的方式,使用者需要通过Cache.cleanUp()的方式来清空缓存。

      所以一般可以有两种选择,一种是通过某个请求来触发清空动作,这种相当于按需清空,另一种则是通过定时任务,亦成为调度程序来清空,这种相当于与按时清空

缓存数据的刷新 
      guava没有提供类似refreshall的方法刷新缓存中的所有值,而只是提供了 LoadingCache.refresh(K)方法,用于刷新某个键值对,这里有趣的是刷新动作是异步的,也就是在值被彻底刷新之前,如果有人取这个key的值,返回的还是没有刷新的值。

      如果你希望定义自己的刷新行为,可以重写 CacheLoader.reload(K, V)方法

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
LoadingCache<Key, Graph> graphs = CacheBuilder.newBuilder()
    .maximumSize( 1000 )
    .refreshAfterWrite( 1 , TimeUnit.MINUTES)
    .build(
        new CacheLoader<Key, Graph>() {
          public Graph load(Key key) {  // no checked exception
            return getGraphFromDatabase(key);
          }
 
          public ListenableFuture<Graph> reload( final Key key, Graph prevGraph) {
            if (neverNeedsRefresh(key)) {
              return Futures.immediateFuture(prevGraph);
            else {
              // asynchronous!
              return ListenableFutureTask.create( new Callable<Graph>() {
                public Graph call() {
                  return getGraphFromDatabase(key);
                }
              });
            }
          }
        });
缓存数据统计 

      可以通过 CacheBuilder.recordStats()方法打开统计, Cache.stats()方法会返回一个CacheStats对象,里面有缓存条目访问率等数据,如果你的缓存需要做一些调优,可以参考这里的数据。


原文地址:http://www.open-open.com/lib/view/open1384351531743.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值