1.引入依赖
GuavaCache是google开源Java类库Guava的其中一个模块,在maven工程下使用可在pom文件加入如下依赖:
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>23.0</version>
</dependency>
2.适用情况
- 你愿意消耗一些内存空间来提升速度。
- 你预料到某些键会被查询一次以上。
- 缓存中存放的数据总量不会超出内存容量。(Guava Cache是单个应用运行时的本地缓存。它不把数据存放到文件或外部服务器。)
3.范例
//LoadingCache在缓存项不存在时可以自动加载缓存
LoadingCache<String,Object> cache = CacheBuilder.newBuilder()
//设置并发级别为8,并发级别是指可以同时写缓存的线程数
.concurrencyLevel(8)
//设置写缓存后8秒钟过期
.expireAfterWrite(8, TimeUnit.SECONDS)
//设置缓存容器的初始容量为10
.initialCapacity(10)
//设置缓存最大容量为100,超过100之后就会按照LRU最近虽少使用算法来移除缓存项
.maximumSize(100)
//设置缓存的移除通知
.removalListener(new RemovalListener<String, Object>() {
@Override
public void onRemoval(
RemovalNotification<String, Object> notification) {
System.out.println(notification.getKey() + " was removed, cause is " + notification.getCause());
}
})
//设置要统计缓存的命中率
.recordStats()
.build(new CacheLoader<String, Object>(){
@Override
public Object load(String key) throws Exception {
return null;
}
});
4.缓存回收
- 基于容量的回收
//规定缓存项的最大数目
CacheBuilder.maximumSize(long)
//指定最大总重(权重)
CacheBuilder.maximumWeight(long)
- 定时回收
//缓存项在给定时间内没有被读/写访问,则回收
expireAfterAccess(long, TimeUnit)
//缓存项在给定时间内没有被写访问(创建或覆盖),则回收
expireAfterWrite(long, TimeUnit)
- 基于引用的回收
//使用弱引用存储键。当键没有其它(强或软)引用时,缓存项可以被垃圾回收。使用弱引用键的缓存用==比较。
CacheBuilder.weakKeys()
CacheBuilder.weakValues()
//使用软引用存储值。软引用只有在响应内存需要时,才按照全局最近最少使用的顺序回收。使用软引用值的缓存同样用==比较。
CacheBuilder.softValues():
- 显示清除
//个别清除
Cache.invalidate(key)
//批量清除
Cache.invalidateAll(keys)
//清除所有缓存项
Cache.invalidateAll()
- 移除监听器
CacheBuilder.removalListener(RemovalListener)//你可以声明一个监听器,以便缓存项被移除时做一些额外操作
- 清理发生时机
使用CacheBuilder构建的缓存不会”自动”执行清理和回收工作,也不会在某个缓存项过期后马上清理。相反,它会在写操作时顺带做少量的维护工作,或者偶尔在读操作时做——如果写操作实在太少的话。
5.缓存类的实现
package baseUtil.common.cache;
import java.util.concurrent.TimeUnit;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.google.common.cache.Weigher;
public abstract class GuavaCache<K,V>{
private LoadingCache<K,V> cache;
public GuavaCache()
{
cache = CacheBuilder.newBuilder()
.maximumSize(1000)
.build(new CacheLoader<K, V>() {
@Override
public V load(K k) throws Exception
{
return loadData(k);
}
});
}
/** * 超时缓存:数据写入缓存超过一定时间自动刷新 * @param duration * @param timeUtil */
public GuavaCache(long duration, TimeUnit timeUtil)
{
cache = CacheBuilder.newBuilder()
.expireAfterWrite(duration, timeUtil)
.build(new CacheLoader<K, V>() {
@Override
public V load(K k) throws Exception
{
return loadData(k);
}
});
}
/** * 限容缓存:缓存数据个数不能超过maxSize * @param maxSize */
public GuavaCache(long maxSize)
{
cache = CacheBuilder.newBuilder()
.maximumSize(maxSize)
.build(new CacheLoader<K, V>() {
@Override
public V load(K k) throws Exception
{
return loadData(k);
}
});
}
/** * 权重缓存:缓存数据权重和不能超过maxWeight * @param maxWeight * @param weigher:权重函数类,需要实现计算元素权重的函数 */
public GuavaCache(long maxWeight, Weigher<K, V> weigher)
{
cache = CacheBuilder.newBuilder()
.maximumWeight(maxWeight)
.weigher(weigher)
.build(new CacheLoader<K, V>() {
@Override
public V load(K k) throws Exception
{
return loadData(k);
}
});
}
/** * 缓存数据加载方法 * @param key */
protected abstract V loadData(K key);
/** * 从缓存获取数据 * @param key * @return value */
public V getData(K key)
{
return cache.getUnchecked(key);
}
/** * 主动设置缓存数据 * @param key * @param value */
public void saveData(K key, V value)
{
cache.put(key, value);
}
/** * 清除单个缓存数据 * @param key */
public void deleteData(K key){
cache.invalidate(key);
}
/** * 清除所有缓存数据 */
public void clear() {
cache.invalidateAll();
}
/** * 刷新缓存数据,数据会重新调用load方法获取 * @param key */
public void refresh(K key)
{
cache.refresh(key);
}
}