Guava 中的缓存

Caches

示例

LoadingCache<Key, Graph> graphs = CacheBuilder.newBuilder()
       .maximumSize(1000)
       .expireAfterWrite(10, TimeUnit.MINUTES)
       .removalListener(MY_LISTENER)
       .build(
           new CacheLoader<Key, Graph>() {
             public Graph load(Key key) throws AnyException {
               return createExpensiveGraph(key);
             }
           });

适用性

缓存在多种场景下都是十分有用的。例如,当值的计算或检索代价很高时,并且您需要多次在某个输入上使用它的值,您应该考虑使用缓存。

Cache 类似于 ConcurrentMap,但并不完全相同。最根本的区别在于 ConcurrentMap 会持久保存添加到其中的所有元素,直到它们被明确移除。另一方面,缓存通常被配置为自动移除元素,以便限制其内存占用。在某些情况下,即使它没有移除元素,由于自​​动缓存加载的特性, LoadingCache 也变得很有用。

通常,Guava 缓存工具程序适用于以下情况:

  • 你愿意花些内存来提高速度。
  • 你希望有时会多次查询键值。
  • 你需要缓存数据的要小于 RAM 的容量。 (Guava 缓存是一个单独运行的应用程序的本地缓存。它们不会将数据存储在文件中或外部服务器上。如果这不符合你的需求,请考虑像 Memcached 这样的工具。)

如果以上几点都适用于您的应用,那么 Guava 缓存工具程序将很适合你!

如上面的示例代码所示,你可以使用 CacheBuilder 构建器模式获取 Cache 对象,但自定义 Cache 也是很有趣的部分。

注意:如果您不需要 Cache 的特性,ConcurrentHashMap 的内存效率会更高 - 但是使用任何旧的 ConcurrentMap 复制大多数 Cache 的功能是极其困难或不可能的。

Population

在设计自己的缓存时要考虑的第一个问题是:是否有一些合理的默认函数来加载或计算与 key 相关的值? 如果是这样,您应该使用 CacheLoader。 如果没有,或者你需要覆盖默认值,但仍然需要原子 “get-if-absent-compute” 语义,则应该将 Callable 传递给 get 调用。 可以使用 Cache.put 直接插入元素,但首选自动缓存加载,因为它可以更容易地推断所有缓存内容的一致性。

From a CacheLoader

LoadingCache 是使用附加的 CacheLoader 构建的 Cache。 创建 CacheLoader 通常与实现 V load(K key) throws Exception 方法一样简单。 因此,例如,您可以使用以下代码创建 LoadingCache

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());
}

查询 LoadingCache 的标准方法是使用方法 get(K)。 这将返回已缓存的值,或者使用 CacheCacheLoader 以原子方式将新值加载到缓存中。 因为 CacheLoader 可能抛出异常,所以 LoadingCache.get(K) 方法签名要抛出 ExecutionException。(如果缓存加载器抛出未检异常, get(K) 将抛出一个包含它的 UncheckedExecutionException。)你还可以选择使用 getUnchecked(K),它包装 UncheckedExecutionException 中的所有异常,但如果底层CacheLoader 正常抛出受检异常,这可能会导致奇怪的行为。

LoadingCache<Key, Graph> graphs = CacheBuilder.newBuilder()
       .expireAfterAccess(10, TimeUnit.MINUTES)
       .build(
           new CacheLoader<Key, Graph>() {
             public Graph load(Key key) { // no checked exception
               return createExpensiveGraph(key);
             }
           });

...
return graphs.getUnchecked(key);

可以使用方法 getAll(Iterable <?extends K>) 执行批量查找。 默认情况下,getAll 将为缓存中不存在的每个密钥发出对 CacheLoader.load 的单独调用。 当批量检索比许多单独查找更有效时,您可以覆盖 CacheLoader.loadAll 来扩展它。 getAll(Iterable) 的性能将相应提高。

请注意,您可以编写一个 CacheLoader.loadAll 实现来加载未特别请求的键的值。 例如,如果计算某个组中任何键的值会为您提供组中所有键的值,则 loadAll 可能会同时加载该组的其余部分。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,736评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,167评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,442评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,902评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,302评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,573评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,847评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,562评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,260评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,531评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,021评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,367评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,016评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,068评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,827评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,610评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,514评论 2 269

推荐阅读更多精彩内容

  • 范例 适用性 缓存在很多场景下都是相当有用的。例如,计算或检索一个值的代价很高,并且对同样的输入需要不止一次获取值...
    爱情小傻蛋阅读 563评论 0 2
  • 缓存 范例 适用性 缓存在很多场景下都是相当有用的。例如,计算或检索一个值的代价很高,并且对同样的输入需要不止一次...
    小鸡在路上阅读 3,190评论 0 2
  • com.google.common.cache 1、背景 缓存,在我们日常开发中是必不可少的一种解决性能问题的方法...
    拾壹北阅读 21,902评论 0 25
  • 创盈移门下料优化管理系统含括了常用门窗系列和门窗款式,如吊趟门、推拉门、平开门、拼格门、艺术门、小折叠、大折叠、封...
    小钰4303阅读 95评论 0 0
  • 2017年过去了,回首这一年,最大的收获是从堕落模式切换到了成长模式。虽然成长不大,但让我看到了希望,我想我的人生...
    李少白阅读 509评论 0 2