Guava緩存

范例

適用性

緩存在很多場(chǎng)景下都是相當(dāng)有用的带兜。例如枫笛,計(jì)算或檢索一個(gè)值的代價(jià)很高,并且對(duì)同樣的輸入需要不止一次獲取值的時(shí)候刚照,就應(yīng)當(dāng)考慮使用緩存刑巧。

Guava Cache與ConcurrentMap很相似,但也不完全一樣无畔。最基本的區(qū)別是ConcurrentMap會(huì)一直保存所有添加的元素啊楚,直到顯式地移除。相對(duì)地浑彰,Guava Cache為了限制內(nèi)存占用恭理,通常都設(shè)定為自動(dòng)回收元素。在某些場(chǎng)景下郭变,盡管LoadingCache 不回收元素颜价,它也是很有用的涯保,因?yàn)樗鼤?huì)自動(dòng)加載緩存。

通常來(lái)說(shuō)周伦,Guava Cache適用于:

  • 你愿意消耗一些內(nèi)存空間來(lái)提升速度夕春。
  • 你預(yù)料到某些鍵會(huì)被查詢(xún)一次以上。
  • 緩存中存放的數(shù)據(jù)總量不會(huì)超出內(nèi)存容量专挪。(Guava Cache是單個(gè)應(yīng)用運(yùn)行時(shí)的本地緩存及志。它不把數(shù)據(jù)存放到文件或外部服務(wù)器。如果這不符合你的需求寨腔,請(qǐng)嘗試Memcached這類(lèi)工具)

如果你的場(chǎng)景符合上述的每一條速侈,Guava Cache就適合你。

如同范例代碼展示的一樣脆侮,Cache實(shí)例通過(guò)CacheBuilder生成器模式獲取锌畸,但是自定義你的緩存才是最有趣的部分。

:如果你不需要Cache中的特性靖避,使用ConcurrentHashMap有更好的內(nèi)存效率——但Cache的大多數(shù)特性都很難基于舊有的ConcurrentMap復(fù)制潭枣,甚至根本不可能做到。

加載

在使用緩存前幻捏,首先問(wèn)自己一個(gè)問(wèn)題:有沒(méi)有合理的默認(rèn)方法來(lái)加載或計(jì)算與鍵關(guān)聯(lián)的值盆犁?如果有的話,你應(yīng)當(dāng)使用CacheLoader篡九。如果沒(méi)有谐岁,或者你想要覆蓋默認(rèn)的加載運(yùn)算,同時(shí)保留"獲取緩存-如果沒(méi)有-則計(jì)算"[get-if-absent-compute]的原子語(yǔ)義榛臼,你應(yīng)該在調(diào)用get時(shí)傳入一個(gè)Callable實(shí)例伊佃。緩存元素也可以通過(guò)Cache.put方法直接插入,但自動(dòng)加載是首選的沛善,因?yàn)樗梢愿菀椎赝茢嗨芯彺鎯?nèi)容的一致性航揉。

CacheLoader

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查詢(xún)的正規(guī)方式是使用get(K)方法。這個(gè)方法要么返回已經(jīng)緩存的值尤蛮,要么使用CacheLoader向緩存原子地加載新值媳友。由于CacheLoader可能拋出異常,LoadingCache.get(K)也聲明為拋出ExecutionException異常产捞。如果你定義的CacheLoader沒(méi)有聲明任何檢查型異常醇锚,則可以通過(guò)getUnchecked(K)查找緩存;但必須注意轧葛,一旦CacheLoader聲明了檢查型異常搂抒,就不可以調(diào)用getUnchecked(K)艇搀。

getAll(Iterable<? extends K>)方法用來(lái)執(zhí)行批量查詢(xún)尿扯。默認(rèn)情況下求晶,對(duì)每個(gè)不在緩存中的鍵,getAll方法會(huì)單獨(dú)調(diào)用CacheLoader.load來(lái)加載緩存項(xiàng)衷笋。如果批量的加載比多個(gè)單獨(dú)加載更高效芳杏,你可以重載CacheLoader.loadAll來(lái)利用這一點(diǎn)。getAll(Iterable)的性能也會(huì)相應(yīng)提升辟宗。

注:CacheLoader.loadAll的實(shí)現(xiàn)可以為沒(méi)有明確請(qǐng)求的鍵加載緩存值爵赵。例如,為某組中的任意鍵計(jì)算值時(shí)泊脐,能夠獲取該組中的所有鍵值空幻,loadAll方法就可以實(shí)現(xiàn)為在同一時(shí)間獲取該組的其他鍵值校注:getAll(Iterable<? extends K>)方法會(huì)調(diào)用loadAll容客,但會(huì)篩選結(jié)果秕铛,只會(huì)返回請(qǐng)求的鍵值對(duì)。

Callable

所有類(lèi)型的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.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)先使用崔涂。

緩存回收

一個(gè)殘酷的現(xiàn)實(shí)是,我們幾乎一定沒(méi)有足夠的內(nèi)存緩存所有數(shù)據(jù)始衅。你你必須決定:什么時(shí)候某個(gè)緩存項(xiàng)就不值得保留了冷蚂?Guava Cache提供了三種基本的緩存回收方式:基于容量回收缭保、定時(shí)回收和基于引用回收。

基于容量的回收(size-based eviction)

如果要規(guī)定緩存項(xiàng)的數(shù)目不超過(guò)固定值蝙茶,只需使用CacheBuilder.maximumSize(long)艺骂。緩存將嘗試回收最近沒(méi)有使用或總體上很少使用的緩存項(xiàng)÷『唬——警告:在緩存項(xiàng)的數(shù)目達(dá)到限定值之前钳恕,緩存就可能進(jìn)行回收操作——通常來(lái)說(shuō),這種情況發(fā)生在緩存項(xiàng)的數(shù)目逼近限定值時(shí)蹄衷。

另外忧额,不同的緩存項(xiàng)有不同的“權(quán)重”(weights)——例如,如果你的緩存值愧口,占據(jù)完全不同的內(nèi)存空間睦番,你可以使用CacheBuilder.weigher(Weigher)指定一個(gè)權(quán)重函數(shù),并且用CacheBuilder.maximumWeight(long)指定最大總重耍属。在權(quán)重限定場(chǎng)景中托嚣,除了要注意回收也是在重量逼近限定值時(shí)就進(jìn)行了,還要知道重量是在緩存創(chuàng)建時(shí)計(jì)算的恬涧,因此要考慮重量計(jì)算的復(fù)雜度注益。


定時(shí)回收(Timed Eviction)

CacheBuilder提供兩種定時(shí)回收的方法:

  • expireAfterAccess(long, TimeUnit):緩存項(xiàng)在給定時(shí)間內(nèi)沒(méi)有被讀/寫(xiě)訪問(wèn),則回收溯捆。請(qǐng)注意這種緩存的回收順序和基于大小回收一樣丑搔。
  • expireAfterWrite(long, TimeUnit):緩存項(xiàng)在給定時(shí)間內(nèi)沒(méi)有被寫(xiě)訪問(wèn)(創(chuàng)建或覆蓋),則回收提揍。如果認(rèn)為緩存數(shù)據(jù)總是在固定時(shí)候后變得陳舊不可用啤月,這種回收方式是可取的。

如下文所討論劳跃,定時(shí)回收周期性地在寫(xiě)操作中執(zhí)行谎仲,偶爾在讀操作中執(zhí)行。

測(cè)試定時(shí)回收

對(duì)定時(shí)回收進(jìn)行測(cè)試時(shí)刨仑,不一定非得花費(fèi)兩秒鐘去測(cè)試兩秒的過(guò)期郑诺。你可以使用Ticker接口和CacheBuilder.ticker(Ticker)方法在緩存中自定義一個(gè)時(shí)間源,而不是非得用系統(tǒng)時(shí)鐘杉武。

基于引用的回收(Reference-based Eviction)

通過(guò)使用弱引用的鍵辙诞、或弱引用的值、或軟引用的值轻抱,Guava Cache可以把緩存設(shè)置為允許垃圾回收:

  • CacheBuilder.weakKeys():使用弱引用存儲(chǔ)鍵飞涂。當(dāng)鍵沒(méi)有其它(強(qiáng)或軟)引用時(shí),緩存項(xiàng)可以被垃圾回收。因?yàn)槔厥諆H依賴(lài)恒等式(==)较店,使用弱引用鍵的緩存用==而不是equals比較鍵士八。
  • CacheBuilder.weakValues():使用弱引用存儲(chǔ)值。當(dāng)值沒(méi)有其它(強(qiáng)或軟)引用時(shí)梁呈,緩存項(xiàng)可以被垃圾回收婚度。因?yàn)槔厥諆H依賴(lài)恒等式(==),使用弱引用值的緩存用==而不是equals比較值捧杉。
  • CacheBuilder.softValues():使用軟引用存儲(chǔ)值陕见。軟引用只有在響應(yīng)內(nèi)存需要時(shí)秘血,才按照全局最近最少使用的順序回收味抖。考慮到使用軟引用的性能影響灰粮,我們通常建議使用更有性能預(yù)測(cè)性的緩存大小限定(見(jiàn)上文仔涩,基于容量回收)。使用軟引用值的緩存同樣用==而不是equals比較值粘舟。

顯式清除

任何時(shí)候熔脂,你都可以顯式地清除緩存項(xiàng),而不是等到它被回收:

  • 個(gè)別清除:Cache.invalidate(key)
  • 批量清除:Cache.invalidateAll(keys)
  • 清除所有緩存項(xiàng):Cache.invalidateAll()

移除監(jiān)聽(tīng)器

通過(guò)CacheBuilder.removalListener(RemovalListener)柑肴,你可以聲明一個(gè)監(jiān)聽(tīng)器霞揉,以便緩存項(xiàng)被移除時(shí)做一些額外操作。緩存項(xiàng)被移除時(shí)晰骑,RemovalListener會(huì)獲取移除通知RemovalNotification适秩,其中包含移除原因RemovalCause鍵和值。

請(qǐng)注意硕舆,RemovalListener拋出的任何異常都會(huì)在記錄到日志后被丟棄[swallowed]秽荞。


警告:默認(rèn)情況下,監(jiān)聽(tīng)器方法是在移除緩存時(shí)同步調(diào)用的抚官。因?yàn)榫彺娴木S護(hù)和請(qǐng)求響應(yīng)通常是同時(shí)進(jìn)行的扬跋,代價(jià)高昂的監(jiān)聽(tīng)器方法在同步模式下會(huì)拖慢正常的緩存請(qǐng)求。在這種情況下凌节,你可以使用RemovalListeners.asynchronous(RemovalListener, Executor)把監(jiān)聽(tīng)器裝飾為異步操作钦听。

清理什么時(shí)候發(fā)生?

使用CacheBuilder構(gòu)建的緩存不會(huì)"自動(dòng)"執(zhí)行清理和回收工作倍奢,也不會(huì)在某個(gè)緩存項(xiàng)過(guò)期后馬上清理朴上,也沒(méi)有諸如此類(lèi)的清理機(jī)制。相反娱挨,它會(huì)在寫(xiě)操作時(shí)順帶做少量的維護(hù)工作余指,或者偶爾在讀操作時(shí)做——如果寫(xiě)操作實(shí)在太少的話。

這樣做的原因在于:如果要自動(dòng)地持續(xù)清理緩存,就必須有一個(gè)線程酵镜,這個(gè)線程會(huì)和用戶操作競(jìng)爭(zhēng)共享鎖碉碉。此外,某些環(huán)境下線程創(chuàng)建可能受限制淮韭,這樣CacheBuilder就不可用了垢粮。

相反,我們把選擇權(quán)交到你手里靠粪。如果你的緩存是高吞吐的蜡吧,那就無(wú)需擔(dān)心緩存的維護(hù)和清理等工作。如果你的 緩存只會(huì)偶爾有寫(xiě)操作占键,而你又不想清理工作阻礙了讀操作昔善,那么可以創(chuàng)建自己的維護(hù)線程,以固定的時(shí)間間隔調(diào)用Cache.cleanUp()畔乙。ScheduledExecutorService可以幫助你很好地實(shí)現(xiàn)這樣的定時(shí)調(diào)度君仆。

刷新

刷新和回收不太一樣。正如LoadingCache.refresh(K)所聲明牲距,刷新表示為鍵加載新值返咱,這個(gè)過(guò)程可以是異步的。在刷新操作進(jìn)行時(shí)牍鞠,緩存仍然可以向其他線程返回舊值咖摹,而不像回收操作,讀緩存的線程必須等待新值加載完成难述。

如果刷新過(guò)程拋出異常萤晴,緩存將保留舊值,而異常會(huì)在記錄到日志后被丟棄[swallowed]龄广。

重載CacheLoader.reload(K, V)可以擴(kuò)展刷新時(shí)的行為硫眯,這個(gè)方法允許開(kāi)發(fā)者在計(jì)算新值時(shí)使用舊的值。


CacheBuilder.refreshAfterWrite(long, TimeUnit)可以為緩存增加自動(dòng)定時(shí)刷新功能择同。和expireAfterWrite相反两入,refreshAfterWrite通過(guò)定時(shí)刷新可以讓緩存項(xiàng)保持可用,但請(qǐng)注意:緩存項(xiàng)只有在被檢索時(shí)才會(huì)真正刷新(如果CacheLoader.refresh實(shí)現(xiàn)為異步敲才,那么檢索不會(huì)被刷新拖慢)裹纳。因此,如果你在緩存上同時(shí)聲明expireAfterWrite和refreshAfterWrite紧武,緩存并不會(huì)因?yàn)樗⑿旅つ康囟〞r(shí)重置剃氧,如果緩存項(xiàng)沒(méi)有被檢索,那刷新就不會(huì)真的發(fā)生阻星,緩存項(xiàng)在過(guò)期時(shí)間后也變得可以回收朋鞍。

其他特性

統(tǒng)計(jì)

CacheBuilder.recordStats()用來(lái)開(kāi)啟Guava Cache的統(tǒng)計(jì)功能已添。統(tǒng)計(jì)打開(kāi)后,Cache.stats()方法會(huì)返回

CacheStats對(duì)象以提供如下統(tǒng)計(jì)信息:

  • hitRate():緩存命中率滥酥;

  • averageLoadPenalty():加載新值的平均時(shí)間更舞,單位為納秒;

  • evictionCount():緩存項(xiàng)被回收的總數(shù)坎吻,不包括顯式清除缆蝉。

此外,還有其他很多統(tǒng)計(jì)信息瘦真。這些統(tǒng)計(jì)信息對(duì)于調(diào)整緩存設(shè)置是至關(guān)重要的刊头,在性能要求高的應(yīng)用中我們建議密切關(guān)注這些數(shù)據(jù)。

asMap視圖

asMap視圖提供了緩存的ConcurrentMap形式诸尽,但asMap視圖與緩存的交互需要注意:

  • cache.asMap()包含當(dāng)前所有加載到緩存的項(xiàng)原杂。因此相應(yīng)地,cache.asMap().keySet()包含當(dāng)前所有已加載鍵;
  • asMap().get(key)實(shí)質(zhì)上等同于cache.getIfPresent(key)弦讽,而且不會(huì)引起緩存項(xiàng)的加載污尉。這和Map的語(yǔ)義約定一致。
  • 所有讀寫(xiě)操作都會(huì)重置相關(guān)緩存項(xiàng)的訪問(wèn)時(shí)間往产,包括Cache.asMap().get(Object)方法和Cache.asMap().put(K, V)方法,但不包括Cache.asMap().containsKey(Object)方法某宪,也不包括在Cache.asMap()的集合視圖上的操作仿村。比如,遍歷Cache.asMap().entrySet()不會(huì)重置緩存項(xiàng)的讀取時(shí)間兴喂。

中斷

緩存加載方法(如Cache.get)不會(huì)拋出InterruptedException蔼囊。我們也可以讓這些方法支持InterruptedException,但這種支持注定是不完備的衣迷,并且會(huì)增加所有使用者的成本畏鼓,而只有少數(shù)使用者實(shí)際獲益。詳情請(qǐng)繼續(xù)閱讀壶谒。

Cache.get請(qǐng)求到未緩存的值時(shí)會(huì)遇到兩種情況:當(dāng)前線程加載值云矫;或等待另一個(gè)正在加載值的線程。這兩種情況下的中斷是不一樣的汗菜。等待另一個(gè)正在加載值的線程屬于較簡(jiǎn)單的情況:使用可中斷的等待就實(shí)現(xiàn)了中斷支持让禀;但當(dāng)前線程加載值的情況就比較復(fù)雜了:因?yàn)榧虞d值的CacheLoader是由用戶提供的,如果它是可中斷的陨界,那我們也可以實(shí)現(xiàn)支持中斷巡揍,否則我們也無(wú)能為力。

如果用戶提供的CacheLoader是可中斷的菌瘪,為什么不讓Cache.get也支持中斷腮敌?從某種意義上說(shuō),其實(shí)是支持的:如果CacheLoader拋出InterruptedException,Cache.get將立刻返回(就和其他異常情況一樣)糜工;此外斗这,在加載緩存值的線程中,Cache.get捕捉到InterruptedException后將恢復(fù)中斷啤斗,而其他線程中InterruptedException則被包裝成了ExecutionException表箭。

原則上钮莲,我們可以拆除包裝免钻,把ExecutionException變?yōu)镮nterruptedException,但這會(huì)讓所有的LoadingCache使用者都要處理中斷異常,即使他們提供的CacheLoader不是可中斷的渤刃。如果你考慮到所有非加載線程的等待仍可以被中斷诫舅,這種做法也許是值得的刊懈。但許多緩存只在單線程中使用,它們的用戶仍然必須捕捉不可能拋出的InterruptedException異常。即使是那些跨線程共享緩存的用戶瓢娜,也只是有時(shí)候能中斷他們的get調(diào)用挂洛,取決于那個(gè)線程先發(fā)出請(qǐng)求。

對(duì)于這個(gè)決定眠砾,我們的指導(dǎo)原則是讓緩存始終表現(xiàn)得好像是在當(dāng)前線程加載值虏劲。這個(gè)原則讓使用緩存或每次都計(jì)算值可以簡(jiǎn)單地相互切換。如果老代碼(加載值的代碼)是不可中斷的褒颈,那么新代碼(使用緩存加載值的代碼)多半也應(yīng)該是不可中斷的柒巫。

如上所述,Guava Cache在某種意義上支持中斷谷丸。另一個(gè)意義上說(shuō)堡掏,Guava Cache不支持中斷,這使得LoadingCache成了一個(gè)有漏洞的抽象:當(dāng)加載過(guò)程被中斷了刨疼,就當(dāng)作其他異常一樣處理泉唁,這在大多數(shù)情況下是可以的;但如果多個(gè)線程在等待加載同一個(gè)緩存項(xiàng)揩慕,即使加載線程被中斷了亭畜,它也不應(yīng)該讓其他線程都失敗(捕獲到包裝在ExecutionException里的InterruptedException)漩绵,正確的行為是讓剩余的某個(gè)線程重試加載贱案。為此,我們記錄了一個(gè)bug止吐。然而,與其冒著風(fēng)險(xiǎn)修復(fù)這個(gè)bug侨糟,我們可能會(huì)花更多的精力去實(shí)現(xiàn)另一個(gè)建議AsyncLoadingCache碍扔,這個(gè)實(shí)現(xiàn)會(huì)返回一個(gè)有正確中斷行為的Future對(duì)象。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末秕重,一起剝皮案震驚了整個(gè)濱河市不同,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌溶耘,老刑警劉巖二拐,帶你破解...
    沈念sama閱讀 217,826評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異凳兵,居然都是意外死亡百新,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,968評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén)庐扫,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)饭望,“玉大人仗哨,你說(shuō)我怎么就攤上這事∏Υ牵” “怎么了厌漂?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,234評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)斟珊。 經(jīng)常有香客問(wèn)我苇倡,道長(zhǎng),這世上最難降的妖魔是什么囤踩? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,562評(píng)論 1 293
  • 正文 為了忘掉前任旨椒,我火速辦了婚禮,結(jié)果婚禮上高职,老公的妹妹穿的比我還像新娘钩乍。我一直安慰自己,他們只是感情好怔锌,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,611評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布寥粹。 她就那樣靜靜地躺著,像睡著了一般埃元。 火紅的嫁衣襯著肌膚如雪涝涤。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,482評(píng)論 1 302
  • 那天岛杀,我揣著相機(jī)與錄音阔拳,去河邊找鬼。 笑死类嗤,一個(gè)胖子當(dāng)著我的面吹牛糊肠,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播遗锣,決...
    沈念sama閱讀 40,271評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼货裹,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了精偿?” 一聲冷哼從身側(cè)響起弧圆,我...
    開(kāi)封第一講書(shū)人閱讀 39,166評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎笔咽,沒(méi)想到半個(gè)月后搔预,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,608評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡叶组,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,814評(píng)論 3 336
  • 正文 我和宋清朗相戀三年拯田,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片扶叉。...
    茶點(diǎn)故事閱讀 39,926評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡勿锅,死狀恐怖帕膜,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情溢十,我是刑警寧澤垮刹,帶...
    沈念sama閱讀 35,644評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站张弛,受9級(jí)特大地震影響荒典,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜吞鸭,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,249評(píng)論 3 329
  • 文/蒙蒙 一寺董、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧刻剥,春花似錦遮咖、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,866評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至漓藕,卻和暖如春陶珠,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背享钞。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,991評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工揍诽, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人栗竖。 一個(gè)月前我還...
    沈念sama閱讀 48,063評(píng)論 3 370
  • 正文 我出身青樓暑脆,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親狐肢。 傳聞我的和親對(duì)象是個(gè)殘疾皇子饵筑,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,871評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容

  • com.google.common.cache 1、背景 緩存处坪,在我們?nèi)粘i_(kāi)發(fā)中是必不可少的一種解決性能問(wèn)題的方法...
    拾壹北閱讀 22,298評(píng)論 0 25
  • 緩存 范例 適用性 緩存在很多場(chǎng)景下都是相當(dāng)有用的。例如架专,計(jì)算或檢索一個(gè)值的代價(jià)很高同窘,并且對(duì)同樣的輸入需要不止一次...
    小雞在路上閱讀 3,235評(píng)論 0 2
  • 適用性緩存在很多情況下都是非常有用的。比如部脚,我們需要多次根據(jù)給定的輸入獲取值想邦,而且該值計(jì)算或者獲取的開(kāi)銷(xiāo)是非常昂貴...
    熊熊要更努力閱讀 838評(píng)論 0 0
  • 管建剛,男委刘,四十多歲丧没,短暫經(jīng)商后又回到學(xué)校鹰椒。近十年來(lái),每年至少出版一本書(shū)呕童。有圖為證: 以上只是我看過(guò)的管老師的一部...
    牽著蝸牌峒剩狂奔閱讀 1,749評(píng)論 1 11
  • 三周基本讀完哈利麗亞雅特.勒納博士著的《憤怒的藝術(shù)》。 人的兩只眼睛長(zhǎng)在一個(gè)方向夺饲,真看不到后面奸汇。 專(zhuān)家就是專(zhuān)家。 ...
    669f9b0cf9d2閱讀 343評(píng)論 6 1