天天看点

Java-类库-Guava-cache

缓存,在我们日常开发中是必不可少的一种解决性能问题的方法。简单的说,cache 就是为了提升系统性能而开辟的一块内存空间。

 缓存在很多系统和架构中都用广泛的应用,例如:

  1.CPU缓存

  2.操作系统缓存

  3.本地缓存

  4.分布式缓存

  5.HTTP缓存

  6.数据库缓存

  等等,可以说在计算机和网络领域,缓存无处不在。可以这么说,只要有硬件性能不对等,涉及到网络传输的地方都会有缓存的身影。

  Guava Cache是一个全内存的本地缓存实现,它提供了线程安全的实现机制。整体上来说Guava cache 是本地缓存的不二之选,简单易用,性能好。

   Guava Cache有两种创建方式:

  1. cacheLoader

  2. callable callback

 通过这两种方法创建的cache,和通常用map来缓存的做法比,不同在于,这两种方法都实现了一种逻辑——从缓存中取key X的值,如果该值已经缓存过了,则返回缓存中的值,如果没有缓存过,可以通过某个方法来获取这个值。但不同的在于cacheloader的定义比较宽泛,是针对整个cache定义的,可以认为是统一的根据key值load value的方法。而callable的方式较为灵活,允许你在get的时候指定

 cacheLoader方式实现实例:

 

callable callback的实现:

 cache的参数说明:

  回收的参数:

  1. 大小的设置:CacheBuilder.maximumSize(long) CacheBuilder.weigher(Weigher) CacheBuilder.maxumumWeigher(long)

  2. 时间:expireAfterAccess(long, TimeUnit) expireAfterWrite(long, TimeUnit)

  3. 引用:CacheBuilder.weakKeys() CacheBuilder.weakValues() CacheBuilder.softValues()

  4. 明确的删除:invalidate(key) invalidateAll(keys) invalidateAll()

  5. 删除监听器:CacheBuilder.removalListener(RemovalListener)

  

  refresh机制:

  1. LoadingCache.refresh(K) 在生成新的value的时候,旧的value依然会被使用。

  2. CacheLoader.reload(K, V) 生成新的value过程中允许使用旧的value

  3. CacheBuilder.refreshAfterWrite(long, TimeUnit) 自动刷新cache

基于泛型的Callable Cache实现:

  说明:Callable只有在缓存值不存在时,才会调用,比如第二次调用getCallableCache(u1name)直接返回缓存中的值

  guava Cache数据移除:

  guava做cache时候数据的移除方式,在guava中数据的移除分为被动移除和主动移除两种。

  被动移除数据的方式,guava默认提供了三种方式:

  1.基于大小的移除:看字面意思就知道就是按照缓存的大小来移除,如果即将到达指定的大小,那就会把不常用的键值对从cache中移除。

  定义的方式一般为 CacheBuilder.maximumSize(long),还有一种一种可以算权重的方法,个人认为实际使用中不太用到。就这个常用的来看有几个注意点,

    其一,这个size指的是cache中的条目数,不是内存大小或是其他;

    其二,并不是完全到了指定的size系统才开始移除不常用的数据的,而是接近这个size的时候系统就会开始做移除的动作;

    其三,如果一个键值对已经从缓存中被移除了,你再次请求访问的时候,如果cachebuild是使用cacheloader方式的,那依然还是会从cacheloader中再取一次值,如果这样还没有,就会抛出异常

  2.基于时间的移除:guava提供了两个基于时间移除的方法

    expireAfterAccess(long, TimeUnit) 这个方法是根据某个键值对最后一次访问之后多少时间后移除

    expireAfterWrite(long, TimeUnit) 这个方法是根据某个键值对被创建或值被替换后多少时间移除

  3.基于引用的移除:

  这种移除方式主要是基于java的垃圾回收机制,根据键或者值的引用关系决定移除

  主动移除数据方式,主动移除有三种方法:

  1.单独移除用 Cache.invalidate(key)

  2.批量移除用 Cache.invalidateAll(keys)

  3.移除所有用 Cache.invalidateAll()

  如果需要在移除数据的时候有所动作还可以定义Removal Listener,但是有点需要注意的是默认Removal Listener中的行为是和移除动作同步执行的,如果需要改成异步形式,可以考虑使用RemovalListeners.asynchronous(RemovalListener, Executor)