龙空技术网

GUAVA缓存使用

举头看蓝天 140

前言:

如今各位老铁们对“guava缓存设置过期时间”都比较珍视,咱们都需要知道一些“guava缓存设置过期时间”的相关内容。那么小编在网络上汇集了一些有关“guava缓存设置过期时间””的相关知识,希望大家能喜欢,同学们快快来了解一下吧!

1、GUAVA缓存介绍Guava Cache是在内存中缓存数据,相比较于数据库或redis存储,访问内存中的数据会更加高效。Guava官网介绍,下面的这几种情况可以考虑使用Guava Cache:愿意消耗一些内存空间来提升速度。预料到某些键会被多次查询。缓存中存放的数据总量不会超出内存容量。 所以,可以将程序频繁用到的少量数据存储到Guava Cache中,以改善程序性能。下面对Guava Cache的用法进行详细的介绍。2、构建缓存对象

可以通过CacheBuilder类构建一个缓存对象,CacheBuilder类采用builder设计模式,它的每个方法都返回CacheBuilder本身,直到build方法被调用。构建一个缓存对象代码如下。

package com.choice; import com.google.common.cache.*; import java.util.concurrent.TimeUnit; /** * @Author: Java * @Date: 2019/1/29 14:49 * @Version 1.0 */ public class CacheUtil { //第一种创建缓存的方式 public final static Cache<Integer, Student> cache = CacheBuilder.newBuilder() //设置最多缓存1000个对象 .maximumSize(1000) //缓存超时时间是30分钟 .expireAfterWrite(30, TimeUnit.MINUTES) .build(); //缓存接口这里是LoadingCache,LoadingCache在缓存项不存在时可以自动加载缓存 public final static LoadingCache<Integer,Student> studentCache //CacheBuilder的构造函数是私有的,只能通过其静态方法newBuilder()来获得CacheBuilder的实例 = CacheBuilder.newBuilder() //设置并发级别为8,并发级别是指可以同时写缓存的线程数 .concurrencyLevel(8) //设置写缓存后8秒钟过期 .expireAfterWrite(8, TimeUnit.SECONDS) //设置缓存容器的初始容量为10 .initialCapacity(10) //设置缓存最大容量为100,超过100之后就会按照LRU最近虽少使用算法来移除缓存项 .maximumSize(100) //设置要统计缓存的命中率 .recordStats() //设置缓存的移除通知 .removalListener(new RemovalListener<Object, Object>() { @Override public void onRemoval(RemovalNotification<Object, Object> notification) { System.out.println(notification.getKey() + " was removed, " + "cause is " + notification.getCause()); } }) //build方法中可以指定CacheLoader,在缓存不存在时通过CacheLoader的实现自动加载缓存 .build( new CacheLoader<Integer, Student>() { @Override public Student load(Integer key) throws Exception { System.out.println("load student " + key); Student student = new Student(); student.setId(key); student.setName("name " + key); return student; } } ); }

上面的代码通过CacheBuilder.newBuilder().build()这句代码创建了二个Cache缓存对象,并在缓存对象中存储了key为Integer,value为Student对象。可以看到Cache非常类似于JDK中的Map,但是相比于Map,Guava Cache提供了很多更强大的功能。

3、使用方法3.1 调用Callable获取缓存中的对象

所有类型的Guava Cache,不管有没有自动加载功能,都支持get(K, Callable)方法。这个方法返回缓存中相应的值,或者用给定的Callable运算并把结果加入到缓存中。在整个加载方法完成前,缓存项相关的可观察状态都不会更改。这个方法简便地实现了模式”如果有缓存则返回;否则运算、缓存、然后返回”。

public Student getStudentById(Integer id) throws Exception{ return CacheUtil.studentCache.get(id,()->{ Student student = new Student(); student.setId(id); student.setName("name " + id); return student; }); }

3.2 将对象显示插入到缓存中

使用如下方法

public void insertStudentIntoCache(Student student){ CacheUtil.studentCache.put(student.getId(),student); }

可以直接向缓存中插入值,这会直接覆盖掉给定键之前映射的值。使用 CacheUtil.studentCache.asMap()视图提供的任何方法也能修改缓存。但请注意,asMap视图的任何方法都不能保证缓存项被原子地加载到缓存中。进一步说,asMap视图的原子运算在Guava Cache的原子加载范畴之外,所以相比于 CacheUtil.studentCache.asMap().putIfAbsent(K,V),Cache.get(K, Callable) 应该总是优先使用。

4、缓存回收4.1 可以指定缓存的大小

public final static Cache<Integer, Student> cache = CacheBuilder.newBuilder() //设置缓存大小 .maximumSize(1000) .expireAfterWrite(30, TimeUnit.MINUTES) .build();

4.2 基于权重回收

权重(感觉用的比较少)不同的缓存项有不同的“权重”(weights)——例如,如果你的缓存值,占据完全不同的内存空间,你可以使用CacheBuilder.weigher(Weigher)指定一个权重函数,并且用CacheBuilder.maximumWeight(long)指定最大总重。在权重限定场景中,除了要注意回收也是在重量逼近限定值时就进行了,还要知道重量是在缓存创建时计算的,因此要考虑重量计算的复杂度

public final static LoadingCache<Integer,Student> studentCache //CacheBuilder的构造函数是私有的,只能通过其静态方法newBuilder()来获得CacheBuilder的实例 = CacheBuilder.newBuilder() //最大权重 .maximumWeight(500) //基于权重回收 .weigher(new Weigher<Integer, Student>() { @Override public int weigh(Integer key, Student value) { int weight = value.getId(); return weight; } }) //设置并发级别为8,并发级别是指可以同时写缓存的线程数 .concurrencyLevel(8) //设置写缓存后8秒钟过期 .expireAfterWrite(8, TimeUnit.SECONDS) //设置缓存容器的初始容量为10 .initialCapacity(10) //设置缓存最大容量为100,超过100之后就会按照LRU最近虽少使用算法来移除缓存项 .maximumSize(100) //设置要统计缓存的命中率 .recordStats() //设置缓存的移除通知 .removalListener(new RemovalListener<Object, Object>() { @Override public void onRemoval(RemovalNotification<Object, Object> notification) { System.out.println(notification.getKey() + " was removed, " + "cause is " + notification.getCause()); } }) //build方法中可以指定CacheLoader,在缓存不存在时通过CacheLoader的实现自动加载缓存 .build( new CacheLoader<Integer, Student>() { @Override public Student load(Integer key) throws Exception { System.out.println("load student " + key); Student student = new Student(); student.setId(key); student.setName("name " + key); return student; } } );

4.3 定时回收

可以参考之前的代码

4.4 基于引用回收

基于引用的回收(Reference-based Eviction)强(strong)、软(soft)、弱(weak)、虚(phantom)引用 通过使用弱引用的键、或弱引用的值、或软引用的值,Guava Cache可以把缓存设置为允许垃圾回收: CacheBuilder.weakKeys():使用弱引用存储键。当键没有其它(强或软)引用时,缓存项可以被垃圾回收。因为垃圾回收仅依赖恒等式(==),使用弱引用键的缓存用==而不是equals比较键。 CacheBuilder.weakValues():使用弱引用存储值。当值没有其它(强或软)引用时,缓存项可以被垃圾回收。因为垃圾回收仅依赖恒等式(==),使用弱引用值的缓存用==而不是equals比较值。 CacheBuilder.softValues():使用软引用存储值。使用软引用值的缓存同样用==而不是equals比较值。

//缓存接口这里是LoadingCache,LoadingCache在缓存项不存在时可以自动加载缓存 public final static LoadingCache<Integer,Student> studentCache //CacheBuilder的构造函数是私有的,只能通过其静态方法newBuilder()来获得CacheBuilder的实例 = CacheBuilder.newBuilder() .weakKeys() .weakValues() .softValues() //设置并发级别为8,并发级别是指可以同时写缓存的线程数 .concurrencyLevel(8) //设置写缓存后8秒钟过期 .expireAfterWrite(8, TimeUnit.SECONDS) //设置缓存容器的初始容量为10 .initialCapacity(10) //设置缓存最大容量为100,超过100之后就会按照LRU最近虽少使用算法来移除缓存项 .maximumSize(100) //设置要统计缓存的命中率 .recordStats() //设置缓存的移除通知 .removalListener(new RemovalListener<Object, Object>() { @Override public void onRemoval(RemovalNotification<Object, Object> notification) { System.out.println(notification.getKey() + " was removed, " + "cause is " + notification.getCause()); } }) //build方法中可以指定CacheLoader,在缓存不存在时通过CacheLoader的实现自动加载缓存 .build( new CacheLoader<Integer, Student>() { @Override public Student load(Integer key) throws Exception { System.out.println("load student " + key); Student student = new Student(); student.setId(key); student.setName("name " + key); return student; } } );

4.5 显示清除

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

个别清除:Cache.invalidate(key)批量清除:Cache.invalidateAll(keys)清除所有缓存项:Cache.invalidateAll()

标签: #guava缓存设置过期时间