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

什么時候使用Cache

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

什么時候使用Guava Cache

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

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

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

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

1、CacheLoader

  • 使用場景:首先問自己一個問題:有沒有合理的默認(rèn)方法來加載或計算與鍵關(guān)聯(lián)的值?如果有的話,你應(yīng)當(dāng)使用CacheLoader.
  • 首選使用,因為它可以更容易地推斷所有緩存內(nèi)容的一致性
  • 使用示例:

LoadingCache是附帶CacheLoader構(gòu)建而成的緩存實(shí)現(xiàn)。創(chuàng)建自己的CacheLoader通常只需要簡單地實(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)方法。這個方法要么返回已經(jīng)緩存的值,要么使用CacheLoader向緩存原子地加載新值


由于CacheLoader可能拋出異常,LoadingCache.get(K)也聲明為拋出ExecutionException異常。如果你定義的CacheLoader沒有聲明任何檢查型異常,則可以通過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,不管有沒有自動加載功能,都支持get(K, Callable<V>)方法。這個方法返回緩存中相應(yīng)的值,或者用給定的Callable運(yùn)算并把結(jié)果加入到緩存中。在整個加載方法完成前,緩存項相關(guān)的可觀察狀態(tài)都不會更改。這個方法簡便地實(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)方法可以直接向緩存中插入值,這會直接覆蓋掉給定鍵之前映射的值。使用Cache.asMap()視圖提供的任何方法也能修改緩存。
但請注意,asMap視圖的任何方法都不能保證緩存項被原子地加載到緩存中。進(jìn)一步說,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)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

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

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

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