Google Guava缓存的学习和使用

 

最近在工作中使用到了Google Guava缓存功能,感觉还是不错,这周末顺便把它深入一点的学习了一下。

     我们为什么需缓存?主要原因是:当计算或获取一个值的时候代价很高,或者频繁获取一个值的时候,我们为了提高系统的性能,就得考虑使用缓存了。而Google Guava的缓存功能就是一种选择。

     那Google Guava缓存适合什么场景用呢?Google Guava官方文档(翻译版)这么说的:

(1)你愿意消耗一些内存空间来提升速度。

(2)你预料到某些键会被查询一次以上。

(3)缓存中存放的数据总量不会超出内存容量。(Guava Cache是单个应用运行时的本地缓存。它不把数据存放到文件或外部服务器。如果这不符合你的需求,请尝试Memcached这类工具)

     只要满足上面任何一点,我们就可以使用Google Guava的缓存功能了。

     现在我们跟着一个demo来了解下它吧。

     1、导入依赖

<dependency>
   <groupId>com.google.guava</groupId>
   <artifactId>guava</artifactId>
   <version>25.1-jre</version>
</dependency>

     2、编写缓存工具类(核心)

    

private static Logger logger = LoggerFactory.getLogger(GuavaUtil.class);

private static RemovalListener<Object, Object> removalListener = new RemovalListener<Object,
 Object>() {
    @Override
    public void onRemoval(RemovalNotification<Object, Object> removal) {
      logger.info(" [{}]被移除原因是 [{}] ",removal.getKey(),removal.getCause());
    }
};
public static LoadingCache<Object,Object> localCache = CacheBuilder.newBuilder()
        .initialCapacity(2)
        .maximumSize(3)
        .expireAfterAccess(1, TimeUnit.MINUTES)
        .expireAfterWrite(1,TimeUnit.MINUTES)
        .removalListener(removalListener)
        .build(new CacheLoader<Object, Object>() {
            @Override
            public Object load(Object o) throws Exception {
                return null;
            }
    });
public static void setKey(Object key,Object value){
    localCache.put(key,value);
    logger.info("[{}]缓存成功",key);
}
public static Object getKey(Object key,Object defultValue){
    try {
        return localCache.get(key);
    } catch (ExecutionException e) {
        logger.info("获取缓存异常",e);
    }catch (CacheLoader.InvalidCacheLoadException e){
        logger.info("没有从缓存中获取到数据,返回为null----");
    }
    return defultValue;
}

知识点:

     (1)LoadingCache是附带CacheLoader构建而成的缓存实现。

     (2)initialCapacity(long) 设置缓存的初始容量

       (3)   maximumSize(long) 设置缓存项目数的最大值,设置它 缓存将会尝试回收不常用的缓存,当然在达到这个限定值之前就可能进行回收操作了。

    (4)expireAfterAccess(long, TimeUnit)  设置定时回收,在给定的时间内没有读/写的访问,则会回收

    (5)expireAfterWrite(30,TimeUnit.MINUTES) 设置定时回收,缓存项在给定时间内没有被写访问(创建或覆盖),则回收。

    (6)removalListener(RemovalListener)  移除监听事件,当缓存被移除时,会出发这个监听事件。

    (7)localCache.put(key,value)向缓存中插入键和值,在demo中我自定义一个setKey()方法来进行插入缓存

    (8)localCache.get(key) 从缓存中取值,在demo中自定义了getKey()方法,对取值进行了一些操作。

 

注意点

      guava不允许返回为null,否则会有如下异常

 com.google.common.cache.CacheLoader$InvalidCacheLoadException:         
 CacheLoader returned null for key name.

     解决办法: (1) 在load()方法中设置 return "null"

                       (2) 在getKey()方法中捕捉该异常 并返回null或者传来的默认值

3、测试

@Controller
public class GuavaController {
    private static org.slf4j.Logger logger = LoggerFactory.getLogger(GuavaUtil.class);
    Map<String, String> map = new HashMap<>();
    {
        map.put("name", "xsh");
        map.put("age", "23");
        map.put("gender", "male");
    }

    @RequestMapping("/guava/{key}")
    @ResponseBody
    public String guavaTest(@PathVariable("key") String key) {
        String result;
        if ((GuavaUtil.getKey(key, null)) == null) {
            GuavaUtil.setKey(key,map.get(key));
            result= map.get(key);
        } else {
            result= (String) GuavaUtil.getKey(key, null);
            logger.info("从缓存中获取[{}]的值为:[{}]",key,result);
        }
        return result;
    }
}

说明:为了测试方便使用了map集合代替了数据库。首先从缓存中查找是否存在key,如果不存在则加入到缓存中,如果存在则从缓存中取。

 

测试结果:

 

本次demo中只使用了缓存的基本功能。详细内容可以查看并发编程网翻译的Google Guava缓存的官网文档:http://ifeve.com/google-guava-cachesexplained/

本文demo的代码:从github上下载demo:https://github.com/520xsh/Guava.git

阅读原文

发布了39 篇原创文章 · 获赞 19 · 访问量 8万+
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 大白 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览