当前位置:首页 > 开发 > 编程语言 > 缓存Cache > 正文

Guava Cache使用笔记

发表于: 2015-07-07   作者:bylijinnan   来源:转载   浏览:
摘要: 1.Guava Cache的get/getIfPresent方法当参数为null时会抛空指针异常 我刚开始使用时还以为Guava Cache跟HashMap一样,get(null)返回null。 实际上Guava整体设计思想就是拒绝null的,很多地方都会执行com.google.common.base.Preconditions.checkNotNull的检查。 2.Guava
1.Guava Cache的get/getIfPresent方法当参数为null时会抛空指针异常

我刚开始使用时还以为Guava Cache跟HashMap一样,get(null)返回null。
实际上Guava整体设计思想就是拒绝null的,很多地方都会执行com.google.common.base.Preconditions.checkNotNull的检查。

2.Guava Cache的load方法不能返回null,否则抛异常

Guava Cache的get方法先在本地缓存中取,如果不存在,则会触发load方法。但load方法不能返回null。

设想这样一个场景:进行某些热点数据查询时,如果缓存中没有,则去数据库中查询,并把查询到的结果保存到缓存中。
但假如说数据库中也没有呢?
这个时候load方法就会抛异常,例如:
public enum TestGuavaCache {

    INSTANCE;

    private LoadingCache<String, Person> infos;

    TestGuavaCache() {
        infos = CacheBuilder.newBuilder().expireAfterAccess(10, TimeUnit.MINUTES).build(new CacheLoader<String, Person>() {
            public Person load(String key) throws Exception {
                //load from database
                Person p = loadFromDatabase();
                return p;
            }
        });
    }

	//假设数据库中不存在
    private Person loadFromDatabase() {
        return null;
    }

    public Person get(String key) {
        try {
            return infos.get(key);
        } catch (Exception e) {
            //log exception
        }
        return null;
    }
}

这是因为Guava Cache认为cache null是无意义的,因此Guava Cache的javadoc里加粗说明: must not be null

现实世界没那么理想,肯定会有null的情况,那怎么处理呢?我的处理一般是对Guava Cache的get方法做try-catch。


有时候cache null也是有意义的,例如对于一个key,假如数据库中也没有对应的value,那就把这个情况记录下来,
避免频繁的查询数据库(例如一些攻击性行为),直接在缓存中就把这个key挡住了。
怎么做呢?举例:

@Test
public void whenNullValue_thenOptional() {
    CacheLoader<String, Optional<String>> loader;
    loader = new CacheLoader<String, Optional<String>>() {
        @Override
        public Optional<String> load(String key) {
            return Optional.fromNullable(getSuffix(key));
        }
    };
 
    LoadingCache<String, Optional<String>> cache;
    cache = CacheBuilder.newBuilder().build(loader);
 
    assertEquals("txt", cache.getUnchecked("text.txt").get());
    assertFalse(cache.getUnchecked("hello").isPresent());
}
private String getSuffix(final String str) {
    int lastIndex = str.lastIndexOf('.');
    if (lastIndex == -1) {
        return null;
    }
    return str.substring(lastIndex + 1);
}


3.什么时候用get,什么时候用getUnchecked

官网文档说:
. If you have defined a CacheLoader that does not declare any checked exceptions then you can perform cache lookups using getUnchecked(K); 
however care must be taken not to call getUnchecked on caches whose CacheLoaders declare checked exceptions.

字面意思是,如果你的CacheLoader没有定义任何checked Exception,那你可以使用getUnchecked。
这一段话我也不是很理解。。官网上给了一个例子是,load方法没有声明throws Exception,那就可以使用getUnchecked:
LoadingCache<Key, Graph> graphs = CacheBuilder.newBuilder()
       .expireAfterAccess(10, TimeUnit.MINUTES)
       .build(
           new CacheLoader<Key, Graph>() {
             public Graph load(Key key) { // no checked exception
               return createExpensiveGraph(key);
             }
           });

...
return graphs.getUnchecked(key);


4.如何定义一个普通的Guava Cache,不需要用到load方法

假如只是简单的把Guava Cache当作HashMap或ConcurrentHashMap的替代品,不需要用到load方法,而是手动地插入,可以这样:
com.google.common.cache.Cache<String, String> cache = CacheBuilder.newBuilder().expireAfterWrite(10, TimeUnit.MINUTES).build();

注意不能用LoadingCache了。
查找:
cache.getIfPresent("xx");
插入:
cache.put("xx", "xxx");

5.Guava Cache的超时机制不是精确的。

我曾经依赖Guava Cache的超时机制和RemovalListener,以实现类似定时任务的功能;后来发现Guava Cache的超时机制是不精确的,例如你设置cache的缓存时间是30秒,
那它存活31秒、32秒,都是有可能的。
官网说:
Timed expiration is performed with periodic maintenance during writes and occasionally during reads, as discussed below.
Caches built with CacheBuilder do not perform cleanup and evict values "automatically," or instantly after a value expires, or anything of the sort. 
Instead, it performs small amounts of maintenance during write operations, or during occasional read operations if writes are rare.







Guava Cache使用笔记

  • 0

    开心

    开心

  • 0

    板砖

    板砖

  • 0

    感动

    感动

  • 0

    有用

    有用

  • 0

    疑问

    疑问

  • 0

    难过

    难过

  • 0

    无聊

    无聊

  • 0

    震惊

    震惊

编辑推荐
Guava作为Google开源出来的工具库,Google自己对Guava的描述:The Guava project contains several
首先说明几点内容,以便更容易理解。 1:设置 expireAfterAccess(long, TimeUnit) 缓存元素在指定的
由于项目的实际情况,需要缓存一些比较不经常改动的数据在本地服务器中,以提高接口处理的速度。决
Java中使用IO Stream直接操作文件的,但是当我们使用这些的时候,往往要经过很多步骤,比如打开文件
Guava针对数学计算,提供了一些很好用的方法,用来完善jdk的math包的不足。 据官方称:guava的math
Guava作为Google开源出来的工具库,Google自己对Guava的描述:The Guava project contains several
1、在实际项目开发中,会使用到很多缓存技术,而且数据库的设计一般也会依赖于有缓存的情况下设计。
1、guava cache 当下最常用最简单的本地缓存 线程安全的本地缓存 类似于ConcurrentHashMap(或者说
1、guava cache 当下最常用最简单的本地缓存 线程安全的本地缓存 类似于ConcurrentHashMap(或者说
1、在实际项目开发中,会使用到很多缓存技术,而且数据库的设计一般也会依赖于有缓存的情况下设计。
版权所有 IT知识库 CopyRight © 2009-2015 IT知识库 IT610.com , All Rights Reserved. 京ICP备09083238号