Guava:Caches 缓存
java guava    2018-09-01 00:12:57    0    0    0
cqc   java guava

  应用场景

  • 你愿意花些内存来提高应用的速度
  • 你所要查询的数据需要花较多时间查询且需要经常查
  • 缓存数据所需要的内存不大于应用的内存

  数据加载

  From a CacheLoader

当缓存不存在时,通过调用loader的load方法去加载缓存
LoadingCache<Key, Graph> graphs = CacheBuilder.newBuilder()
.maximumSize(1000)
.build(
new CacheLoader<Key, Graph>() {
public Graph load(Key key) throws AnyException {
return createExpensiveGraph(key);
}
});

...try {
return graphs.get(key);
} catch (ExecutionException e) {
throw new OtherException(e.getCause());
}
LoadingCacheget(k)方法会抛个检查性异常,若不需要检查性异常可使用getUnchecked(k)方法,其如果有异常,会抛出个运行时异常。

  From a Callable

没有提供load方法,其是通过get(K, Callable<V>)方式处理,当K缓存不存在时,调用Callable方法加载,若缓存存在,则不需要调用Callable。
Cache<Key, Value> cache = CacheBuilder.newBuilder()
.maximumSize(1000)
.build(); // look Ma, no CacheLoader...try {
// If the key wasn't in the "easy to compute" group, we need to
// do things the hard way.
cache.get(key, new Callable<Value>() {
@Override
public Value call() throws AnyException {
return doThingsTheHardWay(key);
}
});
} catch (ExecutionException e) {
throw new OtherException(e.getCause());
}

  Inserted Directly

直接调用cache.put(key, value)

  缓存过期

  Size-based Eviction

CacheBuilder.maximumSize(long) 限制缓存的个数,当超过这个大小的时候,The cache will try to evict entries that haven't been used recently or very often

  Timed Eviction

  • expireAfterAccess(long, TimeUnit) 最近有多久没被访问后, 缓存将被驱逐
  • expireAfterWrite(long, TimeUnit) 从创建或覆盖缓存起,超过多久后缓存将被驱逐

  Explicit Removals 删除缓存

  • individually, using Cache.invalidate(key)
  • in bulk, using Cache.invalidateAll(keys)
  • to all entries, using Cache.invalidateAll()

  Removal Listeners

当缓存被删除时,将会触发监听
CacheLoader<Key, DatabaseConnection> loader = new CacheLoader<Key, DatabaseConnection> () {
public DatabaseConnection load(Key key) throws Exception {
return openConnection(key);
}
};
RemovalListener<Key, DatabaseConnection> removalListener = new RemovalListener<Key, DatabaseConnection>() {
public void onRemoval(RemovalNotification<Key, DatabaseConnection> removal) {
DatabaseConnection conn = removal.getValue();
conn.close(); // tear down properly
}
};

return CacheBuilder.newBuilder()
.expireAfterWrite(2, TimeUnit.MINUTES)
.removalListener(removalListener)
.build(loader);
默认的,触发监听是同步执行的,若监听执行的时间不可忍受,可使用异步的方式RemovalListeners.asynchronous(RemovalListener, Executor)

  Refresh

使用LoadingCache.refresh(K)来刷新缓存, 刷新运作可能会是异步的, 所以在刷新没完全前,你取到的数据还是有可能是旧的.若在刷新时发生异常,将还是使用旧的缓存. 刷新运作也可在配置缓存的时候使用自动刷新操作CacheBuilder.refreshAfterWrite(long, TimeUnit)
// Some keys don't need refreshing, and we want refreshes to be done asynchronously.LoadingCache<Key, Graph> graphs = CacheBuilder.newBuilder()
.maximumSize(1000)
.refreshAfterWrite(1, TimeUnit.MINUTES)
.build(
new CacheLoader<Key, Graph>() {
public Graph load(Key key) { // no checked exception
return getGraphFromDatabase(key);
}

public ListenableFuture<Graph> reload(final Key key, Graph prevGraph) {
if (neverNeedsRefresh(key)) {
return Futures.immediateFuture(prevGraph);
} else {
// asynchronous!
ListenableFutureTask<Graph> task = ListenableFutureTask.create(new Callable<Graph>() {
public Graph call() {
return getGraphFromDatabase(key);
}
});
executor.execute(task);
return task;
}
}
});

  其他

  分析

可通过CacheBuilder.recordStats()来打开分析的功能. Cache.stats()返回一个CacheStats对象,该对象提供了一些有用的分析方法:
  • hitRate(), which returns the ratio of hits to requests
  • averageLoadPenalty(), the average time spent loading new values, in nanoseconds
  • evictionCount(), the number of cache evictions

上一篇: Aggregations 聚合

下一篇: Guava:Multimaps

文档导航