中文官方教程
Github
Guava Cache与ConcurrentMap很相似,但也不完全一样。最基本的区别是ConcurrentMap会一直保存所有添加的元素,
直到显式地移除。相对地,Guava Cache为了限制内存占用,通常都设定为自动回收元素。在某些场景下,尽管LoadingCache 不回收元素,它也是很有用的,因为它会自动加载缓存。
通常来说,Guava Cache适用于:
你愿意消耗一些内存空间来提升速度。
你预料到某些键会被查询一次以上。
缓存中存放的数据总量不会超出内存容量。(Guava Cache是单个应用运行时的本地缓存。它不把数据存放到文件或外部服务器。如果这不符合你的需求,请尝试Memcached这类工具)
如果你的场景符合上述的每一条,Guava Cache就适合你。
————————摘自中文教程
Cache<Object, Object> cache = CacheBuilder.newBuilder()
// 容量大小
.maximumSize(4)
// 设置内部哈希表的大小
.initialCapacity(16)
// 并发数
.concurrencyLevel(4)
// 开启统计功能
.recordStats()
// 设置一个remove监听器
.removalListener(new RemovalListener<Object, Object>() {
@Override
public void onRemoval(RemovalNotification<Object, Object> notification) {
// TODO
}
})
// 定时回收
.expireAfterAccess(30, TimeUnit.MINUTES)
.build();
guava cache提供三种回收方式:容量回收,定时回收,引用回收
CacheBuilder通过 CacheBuilder .maximumSize(long size)
来 设置缓存大小,超过则缓存将尝试回收最近没有使用或总体上很少使用的缓存项。CHOUT
权重函数
CacheBuilder通过 CacheBuilder .weigher(Weigher weigher)
来设置权重函数,
@GwtCompatible
@FunctionalInterface
public interface Weigher<K, V> {
//返回缓存项的权重。参赛重量没有单位;而是简单地相对于彼此。
int weigh(K key, V value);
}
CacheBuilder .maximumWeight(long weight)
来设置最大总重,并且不能和maximumSize一起使用。
cache是如何计算丢弃的:
最大总重会平分到每个Segment,例如总重100,有4个Segment,那每个Segment的重量为25,put数据,如果权重函数的返回值超过该Segment的权重则丢弃该值。
@Test
public void weigherTest() {
Cache<Object, Object> cache = CacheBuilder.newBuilder()
.weigher(new Weigher<Object, Object>() {
@Override
public int weigh(Object key, Object value) {
// 根据value的长度计算
return value.toString().length();
}
}).maximumWeight(100).build();
cache.put("A", "AAAAA"); //Segments[1] 5
cache.put("B", "BBBBBBBBBB");//Segments[1] 10
cache.put("C", "CCCCCCCCCCCCCCC"); // Segments[3] 15
cache.put("D", "DDDDDDDDDDDDDDDDDDDD");//Segments[3] 20
cache.put("E", "EEEEEEEEEEEEEEEEEEEEEEEEE");//Segments[3] 25
cache.put("F", "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF");//Segments[2] 30
cache.asMap().forEach((x,y)->{
System.out.println(y.toString().length()+"\t"+ y);
});
}
输出结果:
25 EEEEEEEEEEEEEEEEEEEEEEEEE
5 AAAAA
10 BBBBBBBBBB
原因:
1, 由于A、B在同一个Segment并且value的长度和没有超过25,所有没有丢弃。
2,C、D、E在同一个Segment,value的和超过25,所以会丢弃前面的C、D,保留了E
3,F在下标为2的Segment里面,value长度超过25,直接丢弃
CacheBuilder提供两种定时回收的方法:
CacheBuilder通过CacheBuilder.recordStats()
开启统计功能;
CacheStats 源码
public final class CacheStats {
// 命中次数
private final long hitCount;
// miss次数
private final long missCount;
// 添加成功次数
private final long loadSuccessCount;
// 添加失败次数
private final long loadExceptionCount;
// 总负载时间
private final long totalLoadTime;
// 驱逐统计
private final long evictionCount;
.......
通过CacheStats.hitRate()方法获取命中率,计算方式:hitCount /(hitCount+missCount)
missRate()方法与此类似,计算方式:missCount /(hitCount+missCount)