Guava 缓存学习

Guava加载缓存的方式

这里值的是当缓存中没有对应键值的时候,guava会自动获取数据的情况,存在两种方式:

  • CacheLoader
  • callable callback

CacheLoader

 private static CacheLoader<String, String> loader = new CacheLoader<String, String>() {
        public String load(String key) throws Exception{
            //加载缓存数据的方法,比如从数据库中获取数据
           
        }
    };
    private static LoadingCache<String, String> guavaCahce = CacheBuilder.newBuilder()
            .build(loader);

从LoadingCache查询的正规方式是使用get(K)方法。这个方法要么返回已经缓存的值,要么使用CacheLoader向缓存原子地加载新值(通过load(String key) 方法加载,上面的例子抛出了异常)。

 private static CacheLoader<String, String> loader = new CacheLoader<String, String>() {
        public String load(String key) {  //这里没有抛出异常
            //加载缓存数据的方法,比如从数据库中获取数据
           
        }
    };
   //那么就可以用getUnchecked(K)访问缓存数据

由于CacheLoader可能抛出异常,LoadingCache.get(K)也声明抛出ExecutionException异常。如果你定义的CacheLoader没有声明任何检查型异常则可以通过getUnchecked(K)查找缓存;但必须注意,一旦CacheLoader声明了检查型异常,就不可以调用getUnchecked(K)

Callable

这种方式不需要在创建的时候指定load方法,但是需要在get的时候实现一个Callable匿名内部类

Cache<Key, Value> cache = CacheBuilder.newBuilder()
    .build(); // look Ma, no CacheLoader

try {
  // If the key wasn't in the "easy to compute" group, we need to
  // do things the hard way.
  cache.get(key, new Callable<Value>() {
    @Override
    public Value call() throws AnyException {
      return doThingsTheHardWay(key);
    }
  });
} catch (ExecutionException e) {
  throw new OtherException(e.getCause());
} 
  • 所有类型的Guava Cache,不管有没有自动加载功能,都支持get(K, Callable)方法。这个方法返回缓存中相应的值,或者用给定的Callable运算并把结果加入到缓存中 在整个加载方法完成前,缓存项相关的可观察状态都不会更改

缓存回收

  • CacheBuilder.maximumSize(size) :设定缓存的容量

  • expireAfterAccess(long, TimeUnit):缓存项在给定时间内没有被读/写访问,则回收。请注意这种缓存的回收顺序和基于大小回收一样。

  • expireAfterWrite(long, TimeUnit):缓存项在给定时间内没有被写访问(创建或覆盖),则回 收。如果认为缓存数据总是在固定时候后变得陈旧不可用,这种回收方式是可取的

  • 通过键值的权重去回收

  CacheLoader<String, String> loader;
        loader = new CacheLoader<String, String>() {
            @Override
            public String load(String key) {
                return key.toUpperCase();
            }
        };

        Weigher<String, String> weighByLength;
        weighByLength = new Weigher<String, String>() {
            @Override
            public int weigh(String key, String value) {
                return value.length();
            }
        };

        LoadingCache<String, String> cache;
        cache = CacheBuilder.newBuilder()
                .maximumWeight(16)
                .weigher(weighByLength)
                .build(loader);

        cache.getUnchecked("first");
        cache.getUnchecked("second");
        cache.getUnchecked("third");
        cache.getUnchecked("last");
        System.out.println( cache.asMap());
        System.out.println(cache.getIfPresent("first"));
        System.out.println( cache.getIfPresent("last"));

基于引用的回收

通过使用弱引用的键、或弱引用的值、或软引用的值,Guava Cache可以把缓存设置为允许垃圾回收:老实说,在网上貌似没怎么看到基于引用的例子,有点一知半解

  • CacheBuilder.weakKeys():使用弱引用存储键。当键没有其它(强或软)引用时,缓存项可以被垃圾回收

  • CacheBuilder.weakValues():使用弱引用存储值。当值没有其它(强或软)引用时,缓存项可以被垃圾回收。

Cache<String,Object> cache = CacheBuilder.newBuilder()
                        .maximumSize(2)
                        .weakValues()
                        .build();
                Object value = new Object();
                cache.put("key1",value);

                value = new Object();//原对象不再有强引用
                System.gc();
               System.out.println(cache.getIfPresent("key1"));
  • CacheBuilder.softValues():使用软引用存储值。软引用只有在响应内存需要时,才按照全局最近最少使用的顺序回收。考虑到使用软引用的性能影响,我们通常建议使用更有性能预测性的缓存大小限定(见上文,基于容量回收)。使用软引用值的缓存同样用==而不是equals比较值。

asMap()

  • asMap 视图的原子运算在Guava Cache的原子加载范畴之外,所以相比于Cache.asMap().putIfAbsent(K,V)不是原子的

  • cache.asMap()包含当前所有加载到缓存的项。因此相应地,cache.asMap().keySet()包含当前所有已加载键;

  • asMap().get(key)实质上等同于cache.getIfPresent(key),而且不会引起缓存项的加载。这和Map的语义约定一致。

  • 所有读写操作都会重置相关缓存项的访问时间,包括Cache.asMap().get(Object)方法和Cache.asMap().put(K, V)方法,但不包括Cache.asMap().containsKey(Object)方法,也不包括在Cache.asMap()的集合视图上的操作。比如,遍历Cache.asMap().entrySet()不会重置缓存项的读取时间。

显示清除

任何时候,你都可以显式地清除缓存项,而不是等到它被回收:

  • 个别清除:Cache.invalidate(key)

  • 批量清除:Cache.invalidateAll(keys)

  • 清除所有缓存项:Cache.invalidateAll()

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值