java本地缓存-LoadingCache使用

缓存的作用是用来保存一些程序运行中需要经常用的数据。这些数据如果存在数据库,频繁的访问数据库会增加数据库的负载。所以要将这些数据放在本地缓存中,并定时更新。

LoadingCache的使用过程中主要涉及两个类LoadingCache和CacheBuilder。

CacheBuilder使用来定义一些更新删除策略,最后生成LoadingCache对象。

CacheBuilder的主要方法:

refreshAfterWrite(long, TimeUnit):缓存增加自动定时刷新功能。在获取数据的时候如果发现数据被写入超过了指定的时间间隔,就从新调用加载方法加载值。

maximumSize(long size):配置缓存数量上限,快达到上限或达到上限时,会尝试回收最近没有使用或总体上很少使用的缓存。

expireAfterAccess(long, TimeUnit):缓存项在给定时间内没有被读/写访问,则回收。这种缓存的回收顺序和maximumSize()方法的回收机制一样。

expireAfterWrite(long, TimeUnit):缓存项在给定时间内没有被写访问(创建或覆盖),则回收。如果我们的缓存数据在指定的时间之后就需要从新加载,就可以使用这种机制。

build(CacheLoader<? super K1, V1> loader):数据加载方法,当获取的数据不存在、数据刷新时都会通过CacheLoader.load(String)来加载数据最新的数据。

removalListener(RemovalListener):监听器,在缓存项被移除时做一些额外操作。缓存项被移除时,会获取移除通知RemovalNotification,其中包含移除原因RemovalCause、键和值。监听器的方法调用是同步的,不建议执行耗时操作。如果需要可以通过异步的方法来执行,异步方法可以使用 RemovalListeners.asynchronous() 执行方法如下:

private RemovalListener getsyncRemovalListener(){
        MyRemovalListener myRemovalListener = new MyRemovalListener();
         //异步移除监听器
        return RemovalListeners.asynchronous(myRemovalListener, new MessageHandleExecutors().messageHandleTaskExecutor());
    }

    public class MyRemovalListener implements RemovalListener {
        @Override
        public void onRemoval(RemovalNotification notification) {
            System.out.println(String.format("数据移除原因:%s, key : %s, value:%s", notification.getCause().toString(), notification.getKey(), notification.getKey()));
        }
    }

移除操作必须要外部触发条件,如果缓存一直没有被访问,那么监听器一直不会被触发。如果有缓存的访问(刷新\删除)操作就会触发所有数据的的移除计算。一旦达到要求就会被移除。但是asMap(),以及asMap的后续方法不会触发数据的的移除计算操作。初次之外, loadingcache的put操作也会触发移除监听器,包括put已经存在的数据。

recordStats() :用来开启Guava Cache的统计功能。统计打开后,Cache.stats()方法会返回CacheStats对象以提供如下统计信息

hitRate():缓存命中率。
averageLoadPenalty():加载新值的平均时间,单位为纳秒。
evictionCount():缓存项被回收的总数,不包括显式清除。

使用CacheBuilder获取LoadingCache实例(LocalLoadingCache)的方法如下:

public class MyLoadingCache {

    public LoadingCache<String, Optional<Object>> initLoadingCache(){
        return CacheBuilder.newBuilder()
                .maximumSize(20)
                .expireAfterAccess(10, TimeUnit.SECONDS)
                .refreshAfterWrite(5, TimeUnit.SECONDS)
                .removalListener(new MyRemovalListener())   //移除监听器
                .build(new MyCacheLoader());
    }



    private RemovalListener getsyncRemovalListener(){
        MyRemovalListener myRemovalListener = new MyRemovalListener();
         //异步移除监听器
        return RemovalListeners.asynchronous(myRemovalListener, new MessageHandleExecutors().messageHandleTaskExecutor());
    }

    public class MyRemovalListener implements RemovalListener {
        @Override
        public void onRemoval(RemovalNotification notification) {
            System.out.println(String.format("数据移除原因:%s, key : %s, value:%s", notification.getCause().toString(), notification.getKey(), notification.getKey()));
        }
    }

    public class MyCacheLoader extends CacheLoader<String, Optional<Object>> {
        @Override
        public Optional<Object> load(String key) throws Exception {
            System.out.println("从新获取" + key + "的值");
            return Optional.ofNullable(key + "_value");
        }
    }
}

 LoadingCache的主要方法:

get(K):存缓存中获取值,如果缓存没有,则会先调用load()加载再返回加载结果。如果结果为null会抛出异常。
getIfPresent():存缓存中获取值,如果缓存没有,则会先调用load()加载再返回加载结果。如果结果为null会返回null.不会抛出异常。
getAllPresent():存缓存中获取值,如果缓存没有,则会先调用load()加载再返回加载结果。如果结果为null会返回null.不会抛出异常。
put(key, value):直接显示地向缓存中插入值,如果原来缓存里面已经存在则会覆盖原有的值。
invalidate(key):清除单个。
invalidateAll(keys) :批量清除。
invalidateAll():清除所有缓存。
refresh(key):刷新键值,可以是异步。在刷新操作进行时,缓存仍然可以向其他线程返回旧值,而不像回收操作,读缓存的线程必须等待新值加载完成。如果刷新过程抛出异常,缓存将保留旧值,而异常会在记录到日志后被丢弃。重载CacheLoader.reload(K, V)可以扩展刷新时的行为,这个方法允许开发者在计算新值时使用旧的值。
asMap():返回ConcurrentMap视图。asMap().get(key)实质上等同于cache.getIfPresent(key),而且不会引起缓存项的加载。这和Map的语义约定一致。asMap()之后的所有读写操作都会重置相关缓存项的访问时间,包括Cache.asMap().get(Object)方法和Cache.asMap().put(K, V)方法,但是一些遍历操作和判断操作不会重置缓存的访问时间,如Cache.asMap().containsKey(Object)Cache.asMap().entrySet()。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值