使用guava作内存缓存,大多数小伙伴应该都使用过,通过CacheBuilder
创建LoadingCache
一个kv格式的缓存,如果我们需要缓存的只是一个value呢?
针对这种场景,接下来介绍一种基于Supplier
来实现的缓存方式
1. Supplier使用姿势
guava的Supplier与jdk的Supplier从接口定义上来看没什么区别,对外只提供了一个get()
方法
@FunctionalInterface@GwtCompatiblepublicinterfaceSupplier<T>extendsjava.util.function.Supplier<T>{@CanIgnoreReturnValueTget();}
重点需要关注的是Supplier创建的姿势,借助Suppliers
来实现
下面是几个常见的创建姿势:
memoize
: delegate为具体的获取值的委托类,需要注意的是,delegate的具体实现只会在首次时调用;这种方式相当于持久缓存
memoizeWithExpiration
:delegate的返回值,会缓存一段时间;缓存时间过后,会重新调用一下delegate来获取返回值
ofInstance
: 直接传参
publicstatic<T>Supplier<T>memoize(Supplier<T>delegate)publicstatic<T>Supplier<T>memoizeWithExpiration(Supplier<T>delegate,longduration,TimeUnitunit)publicstatic<T>Supplier<T>ofInstance(@NullableTinstance)
基于上面的方法描述,如果我们想实现一个10s缓存,那么可以选择memoizeWithExpiration
来实现
AtomicIntegeratomicInteger=newAtomicInteger(1);Supplier<Integer>cache=Suppliers.memoizeWithExpiration(this::ret,10,TimeUnit.SECONDS);privateintret(){System.out.println("-------更新value--------");returnatomicInteger.getAndAdd(2);}
上面定义了一个内存缓存cache
, 缓存10s,调用时若缓存失效,会重新调用ret()
刷新缓存
测试case就比较简单了
@TestpublicvoidtestSupplier()throwsInterruptedException{for(inti=0;i<10;i++){System.out.print(cache.get()+"|");}System.out.println();Thread.sleep(10000);System.out.println(cache.get());}
输出如下
-------更新value--------1|1|1|1|1|1|1|1|1|1|-------更新value--------3
2. 缓存刷新
使用Supplier当缓存时,需要注意的一点就是没有缓存失效的方法可供调用;对于LoadingCache
若是想失效缓存,可以通过调用 invalidate
来主动失效指定的缓存,那么Supplier 可以怎么整?
直接重新赋值
比如当我们希望刷新时,可以直接覆盖就的supplier即可
publicvoidrefresh(){cache=Suppliers.memoizeWithExpiration(this::ret,10,TimeUnit.SECONDS);}
公众号:一灰灰blog