0. 前言

为了更加有效的使用资源,任何项目中都必须考虑缓存问题。需要结合实际去考虑如何构架。 这里主要总结下如何借用 Guava Cache 使用 jVM 缓存。

1. 初始化,两种方式

初始化时定义数据加载源

LoadingCache<Object, Graph> cache = CacheBuilder.newBuilder()
    .maximumSize(10000)
    .expireAfterWrite(10, TimeUnit.SECONDS)
    .build(new CacheLoader<Object, Object>() {
        @Override
        public Graph load(Graph o) throws Exception {
            return createExpensiveGraph(key);
        }
    });
Object value = cache.get("key");

在使用get()时定义数据加载源

Cache<String, Object> cache = CacheBuilder.newBuilder().maximumSize(1000).build();
Object value = cache.get("key", new Callable<Object>() {
    public Object call() {
        createExpensiveGraph(key);
    }
});

使用第二种定义方式可以在为每个key定义数据加载方式。好像更加灵活。

不过第一种也可以在get(key, Callable)时重新实现数据加载方式。

2. expireAfterWrite refreshAfterWrite 区别

  • CacheBuilder.newBuilder().expireAfterWrite(1, TimeUnit.SECONDS);

    当Cache里面有多个值过期,未设置自动清除过期数据,

    cache.size() # 过期数据仍然在Cache里面

    cache.get(“key”) # 将清楚所有过期数据,若key过期会重新加载

  • CacheBuilder.newBuilder().refreshAfterWrite(1, TimeUnit.SECONDS);

    当Cache里面有多个值过期,未设置自动清除过期数据,

    cache.size() # 过期数据仍然在Cache里面

    cache.get(“key”) # 将更新所有过期数据(包括其他过期的key),

3. expireAfterWrite expireAfterAccess 区别

  • expireAfterAccess(long, TimeUnit)
    基于访问(read or write),以最后一次访问时间算

  • expireAfterWrite(long, TimeUnit)
    基于创建(after create),以创建时间计算

4. 回收的参数设置

  • 大小的设置:CacheBuilder.maximumSize(long) CacheBuilder.weigher(Weigher) CacheBuilder.maxumumWeigher(long)
  • 时间:expireAfterAccess(long, TimeUnit) expireAfterWrite(long, TimeUnit)
  • 引用:CacheBuilder.weakKeys() CacheBuilder.weakValues() CacheBuilder.softValues()
  • 明确的删除:invalidate(key) invalidateAll(keys) invalidateAll()
  • 删除监听器:CacheBuilder.removalListener(RemovalListener)

5. refresh机制

  • LoadingCache.refresh(K) 在生成新的value的时候,旧的value依然会被使用。
  • CacheLoader.reload(K, V) 生成新的value过程中允许使用旧的value
  • CacheBuilder.refreshAfterWrite(long, TimeUnit) 自动刷新cache

设置自动清除cache,可将未过期的cache清除,到期的缓存会自动被清除掉

  • Cache.invalidate(key)
  • Cache.invalidateAll(keys)
  • Cache.invalidateAll()

手动清除过期缓存,方法被调用是执行,可以定义定时器定期清除。

  • cache.cleanUp();

直接往cache里面放数据,而不是其他方式加载。

  • cache.put(key,value);
  • cache.putAll(Map);