缓存写入的方式
CacheLoader填充
@Test
public void testCache () {
//如果找不到,执行loadFromDB()
CacheLoader<String, Employee> cacheLoader = CacheLoader.from(key ->
loadFromDb(key)
);
LoadingCache<String, Employee> cache = CacheBuilder.newBuilder()
.maximumSize(10)
.build(cacheLoader);
// cache.put("");
Employee alice = cache.getUnchecked("Alice");
log.info(alice.toString());
}
Callable填充
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Employee {
private String name;
private String empno;
}
@Test
public void testCacheCallback () {
Cache<String, Employee> cache = CacheBuilder.newBuilder()
.maximumSize(10)
.build();
try {
// 如果从缓存中获取不到,执行callback,加载到缓存中
Employee alice = cache.get("Alice",()->
loadFromDb("Alice")
);
log.info(alice.toString());
} catch (ExecutionException e) {
e.printStackTrace();
}
}
直接填充
@Test
public void testInsertedDirectly() {
Cache<String, Employee> cache = CacheBuilder.newBuilder()
.maximumSize(10)
.build();
@Nullable Employee employee = cache.getIfPresent("Alice");
Assert.assertNull(employee);
cache.put("Alice",new Employee("Alice",UUID.randomUUID().toString()));
employee = cache.getIfPresent("Alice");
Assert.assertNotNull(employee);
}
驱逐策略
基于size驱逐
驱逐顺序按照最近或经常未使用的
@Test
public void testSizeBasedEviction() {
Cache<String, Employee> cache = CacheBuilder.newBuilder()
// 还可以设置权重
// .weigher(new Weigher<String, Employee>() {
// @Override
// public int weigh(String key, Employee value) {
// return 0;
// }
// })
.maximumSize(3)
.build();
cache.put("Alice1",new Employee("Alice1",UUID.randomUUID().toString()));
cache.put("Alice2",new Employee("Alice2",UUID.randomUUID().toString()));
cache.put("Alice3",new Employee("Alice3",UUID.randomUUID().toString()));
ConcurrentMap<String, Employee> asMap = cache.asMap();
System.out.println(asMap);
cache.put("Alice4",new Employee("Alice4",UUID.randomUUID().toString()));
asMap = cache.asMap();
System.out.println(asMap);
}
定时驱逐
- expireAfterAccess(long, TimeUnit) 上次读取或写入经过指定的持续时间后过期。逐出条目的顺序将类似于基于大小的逐出。
- expireAfterWrite(long, TimeUnit)
基于引用的驱逐
- CacheBuilder.weakKeys()使用弱引用存储密钥。如果没有其他(强或软)键引用,则允许对条目进行垃圾回收。由于垃圾回收仅取决于身份相等性,因此这导致整个缓存使用身份(==)相等性来比较键,而不是equals()。
- CacheBuilder.weakValues()使用弱引用存储值。如果没有其他(强或软)值引用,则可以垃圾回收这些条目。由于垃圾回收仅取决于身份相等性,因此这导致整个缓存使用身份(==)相等性比较值,而不是equals()。
- CacheBuilder.softValues()将值包装在软引用中。响应内存需求,以全局最近最少使用的方式对软引用的对象进行垃圾回收。由于使用软引用会对性能产生影响,因此我们通常建议使用更可预测的最大高速缓存大小。使用softValues()将导致使用标识(==)相等而不是equals()来比较值。