填充策略
Caffeine提供了4中填充策略:手动加载、同步加载以及异步变体(异步手工、异步加载)。
手动加载
Cache<Key, Graph> cache = Caffeine.newBuilder()
.expireAfterWrite(10, TimeUnit.MINUTES)
.maximumSize(10_000)
.build();
// Lookup an entry, or null if not found
Graph graph = cache.getIfPresent(key);
// Lookup and compute an entry if absent, or null if not computable
graph = cache.get(key, k -> createExpensiveGraph(key));
// Insert or update an entry
cache.put(key, graph);
// Remove an entry
cache.invalidate(key);
Cache接口允许对缓存条目进行明确的检索、更新以及无效操作。
可以通过cache.put(key, value)插入条目,他会覆盖指定key在缓存内的原有值。为了避免与其他写操作竞争,我们推荐使用cache.get(key, k -> value)方法自动计算并将value写入缓存。注意,如果条目不可计算,cache.get可能返回null;如果计算失败,这抛出异常。
通过Cache.asMap()获取ConcurrentMap视图,所有基于ConcurrentMap方法的改变都会反映到缓存上。
自动加载
LoadingCache<Key, Graph> cache = Caffeine.newBuilder()
.maximumSize(10_000)
.expireAfterWrite(10, TimeUnit.MINUTES)
.build(key -> createExpensiveGraph(key));
// Lookup and compute an entry if absent, or null if not computable
Graph graph = cache.get(key);
// Lookup and compute entries that are absent
Map<Key, Graph> graphs = cache.getAll(keys);
LoadingCache是使用附加CacheLoader构件的缓存。
可以使用getAll方法执行批量查询。默认情况下,对于缓存中不存在的每个key,getAll都会对CacheLoader.load发出单独的调用。当批量检索比多个单独查找更为有效时,可以重写CacheLoader.loadAll方法来实现它。
注意,您可以编写CacheLoader.loadAll实现来加载那些未明确请求的key的值。例如,如果计算某个组中任何key的值为您提供了该组中所有key的值,loadAll可能会同时加载改组中的其余key。???
异步手动加载
AsyncCache<Key, Graph> cache = Caffeine.newBuilder()
.expireAfterWrite(10, TimeUnit.MINUTES)
.maximumSize(10_000)
.buildAsync();
// Lookup and asynchronously compute an entry if absent
CompletableFuture<Graph> graph = cache.get(key, k -> createExpensiveGraph(key));
AsyncCache是Cache的变体,它通过Executor计算条目并返回CompletableFuture。这允许通过利用流行的响应式编程模型使用缓存。
synchronous() 视图提供了一个Cache,它会一直阻塞直到所有的异步计算完成为止。
通过AsyncCache.asMap()获取ConcurrentMap视图,所有基于ConcurrentMap方法的改变都会反映到缓存上。
默认的Executor是 ForkJoinPool.commonPool(),它可以通过Caffeine.executor(Executor)方法重写。
异步自动加载
AsyncLoadingCache<Key, Graph> cache = Caffeine.newBuilder()
.maximumSize(10_000)
.expireAfterWrite(10, TimeUnit.MINUTES)
// Either: Build with a synchronous computation that is wrapped as asynchronous
.buildAsync(key -> createExpensiveGraph(key));
// Or: Build with a asynchronous computation that returns a future
.buildAsync((key, executor) -> createExpensiveGraphAsync(key, executor));
// Lookup and asynchronously compute an entry if absent
CompletableFuture<Graph> graph = cache.get(key);
// Lookup and asynchronously compute entries that are absent
CompletableFuture<Map<Key, Graph>> graphs = cache.getAll(keys);
AsyncLoadingCache是使用附加的AsyncCacheLoader构件的AsyncCache。
当值的计算最好采用同步方式进行的时候,应提供CacheLoader。与之对应的,当值的计算是异步进行并且返回CompletableFuture时,应提供AsyncCacheLoader。