Guava Cache系列之一:如何加載緩存

什么時(shí)候使用Cache

計(jì)算或檢索一個(gè)值的代價(jià)很高,或者是讀多寫少的場(chǎng)景,就應(yīng)當(dāng)考慮使用緩存。

什么時(shí)候使用Guava Cache

  • 緩存中存放的數(shù)據(jù)總量不會(huì)超出內(nèi)存容量。(Guava Cache是單個(gè)應(yīng)用運(yùn)行時(shí)的本地緩存。它不把數(shù)據(jù)存放到文件或外部服務(wù)器)
  • Guava Cache與ConcurrentMap很相似,但也不完全一樣。

最基本的區(qū)別是:
1、ConcurrentMap會(huì)一直保存所有添加的元素,直到顯式地移除。
2、相對(duì)地,Guava Cache為了限制內(nèi)存占用,通常都設(shè)定為自動(dòng)回收元素。在某些場(chǎng)景下,盡管LoadingCache不回收元素,它也是很有用的,因?yàn)樗鼤?huì)自動(dòng)加載緩存。

緩存內(nèi)容如何加載

Guava Cache 加載有三種方式:1、CacheLoader;2、調(diào)用get時(shí)傳入一個(gè)Callable實(shí)例;3、Cache.put方法直接插入。那么何時(shí)使用何種方法呢?

1、CacheLoader

  • 使用場(chǎng)景:首先問(wèn)自己一個(gè)問(wèn)題:有沒(méi)有合理的默認(rèn)方法來(lái)加載或計(jì)算與鍵關(guān)聯(lián)的值?如果有的話,你應(yīng)當(dāng)使用CacheLoader.
  • 首選使用,因?yàn)樗梢愿菀椎赝茢嗨芯彺鎯?nèi)容的一致性
  • 使用示例:

LoadingCache是附帶CacheLoader構(gòu)建而成的緩存實(shí)現(xiàn)。創(chuàng)建自己的CacheLoader通常只需要簡(jiǎn)單地實(shí)現(xiàn)V load(K key) throws Exception方法。例如,你可以用下面的代碼構(gòu)建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查詢的正規(guī)方式是使用get(K)方法。這個(gè)方法要么返回已經(jīng)緩存的值,要么使用CacheLoader向緩存原子地加載新值


由于CacheLoader可能拋出異常,LoadingCache.get(K)也聲明為拋出ExecutionException異常。如果你定義的CacheLoader沒(méi)有聲明任何檢查型異常,則可以通過(guò)getUnchecked(K)查找緩存;但必須注意,一旦CacheLoader聲明了檢查型異常,就不可以調(diào)用getUnchecked(K)。

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

2、Callable

所有類型的Guava Cache,不管有沒(méi)有自動(dòng)加載功能,都支持get(K, Callable<V>)方法。這個(gè)方法返回緩存中相應(yīng)的值,或者用給定的Callable運(yùn)算并把結(jié)果加入到緩存中。在整個(gè)加載方法完成前,緩存項(xiàng)相關(guān)的可觀察狀態(tài)都不會(huì)更改。這個(gè)方法簡(jiǎn)便地實(shí)現(xiàn)了模式"如果有緩存則返回;否則運(yùn)算、緩存、然后返回"。

Cache<Key, Graph> 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<Key, Graph>() {
        @Override
        public Value call() throws AnyException {
            return doThingsTheHardWay(key);
        }
    });
} catch (ExecutionException e) {
    throw new OtherException(e.getCause());
}

3、顯式插入

使用cache.put(key, value)方法可以直接向緩存中插入值,這會(huì)直接覆蓋掉給定鍵之前映射的值。使用Cache.asMap()視圖提供的任何方法也能修改緩存。
但請(qǐng)注意,asMap視圖的任何方法都不能保證緩存項(xiàng)被原子地加載到緩存中。進(jìn)一步說(shuō),asMap視圖的原子運(yùn)算在Guava Cache的原子加載范疇之外,所以相比于Cache.asMap().putIfAbsent(K,V),Cache.get(K, Callable<V>) 應(yīng)該總是優(yōu)先使用。

參考文章

CachesExplained

下一篇文章:Guava Cache系列之二:如何回收緩存

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • com.google.common.cache 1、背景 緩存,在我們?nèi)粘i_(kāi)發(fā)中是必不可少的一種解決性能問(wèn)題的方法...
    拾壹北閱讀 22,736評(píng)論 0 25
  • Spring Cloud為開(kāi)發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見(jiàn)模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,569評(píng)論 19 139
  • 遍城河淺水清清,歸岸懶鴨碎柳迎。 荒草桃花稍印色,牧童非牧怕傷情。
    撲忒閱讀 369評(píng)論 0 5
  • 如何對(duì)比一家公司 我們應(yīng)該從影響公司存量的因素入手 也就是從內(nèi)部入手.我們的目的是比對(duì)企業(yè)所具備得高效 快速提供富...
    taylor_tiger閱讀 417評(píng)論 0 0
  • 有時(shí)候在夜晚看著這樣的天,會(huì)不會(huì)覺(jué)得很寂寞,因?yàn)槟愕乃?她不在你的身邊,你會(huì)很想他/她,很想很想,但是沒(méi)用!因?yàn)槟?..
    黑色的小獅子閱讀 1,304評(píng)論 1 1

友情鏈接更多精彩內(nèi)容