翻譯自Google Guava Cachehtml
This Post is a continuation of my series on Google Guava, this time covering Guava Cache. Guava Cache offers more flexibility and power than either a HashMap or ConcurrentHashMap, but is not as heavy as using EHCache or Memcached (or robust for that matter, as Guava Cache operates solely in memory). The Cache interface has methods you would expect to see like ‘get’, and ‘invalidate’. A method you won’t find is ‘put’, because Guava Cache is ‘self-populating’, values that aren’t present when requested are fetched or calculated, then stored. This means a ‘get’ call will never return null. In all fairness, the previous statement is not %100 accurate. There is another method ‘asMap’ that exposes the entries in the cache as a thread safe map. Using ‘asMap’ will result in not having any of the self loading operations performed, so calls to ‘get’ will return null if the value is not present (What fun is that?). Although this is a post about Guava Cache, I am going to spend the bulk of the time talking about CacheLoader and CacheBuilder. CacheLoader specifies how to load values, and CacheBuilder is used to set the desired features and actually build the cache.java
這篇文章是個人Google Guava系列文章的延續,此次的主題是Guava Cache。Guava Cahce比HashMap和ConcurrentHashMap更靈活也更強大,可是又不像使用EHCache或者Memcached(所以也不像它們這麼健壯,由於Guava Cache只在內存中操做)那麼重量級。Guava Cache有你期待的接口,像是'get',以及'invalide'。一個你不會發現的方法是'put', 由於Guava Cache是「自填充」的,在請求時沒有出現的值會被抓取或者計算,而後儲存起來。因此'get'方法永遠不會返回null。公平地說,上邊一句並非100%準確的。還有一個方法叫作‘asMap',把cache中的條目做爲一個線程安全的map暴露出來。使用'asMap'並不會執行任何自填充操做,所以,若是值不存在的話,調用'get'會返回null(這麼作有啥意義呢?)儘管這篇blog是關於Guava Cache的,我也會花不少時間講CacheLoader和CacheBuilder。CacheLoader用來指明怎麼樣加載值,而CacheBuilder用於設置你想要的特性,而且實際用來建立cache。git
CacheLoader is an abstract class that specifies how to calculate or load values, if not present. There are two ways to create an instance of a CacheLoader:github
Extend the CacheLoader<K,V> class算法
Use the static factory method CacheLoader.from緩存
CacheLoader是一個抽象類,用來指明怎麼樣計算或者加載值,若是沒有發現的話(譯註:若是沒有在緩存裏)。有兩種方法來創建一個CacheLoader的實例:安全
If you extend CacheLoader you need to override the V load(K key)
method, instructing how to generate the value for a given key. Using the static CacheLoader.from
method you build a CacheLoader either by supplying a Function or Supplier interface. When supplying a Function object, the Function is applied to the key to calculate or retrieve the results. Using a Supplier interface the value is obtained independent of the key.併發
若是你擴展CacheLoader,你須要覆蓋V load(K key)方法,來講明怎麼樣從一個指定的key生成value。使用靜態的CacheLoader.from方法來構造CacheLoader時,你或者提供一個Function接口或者Supplier接口(譯註:應該是說「實現了Function或者Supplier接口的對象")。當提供一個Function對象時,這個Function被用於根據key來計算或者獲取結果。使用一個Supplier接口時,value的獲取和key沒有關係。app
The CacheBuilder is used to construct cache instances. It uses the fluent style of building and gives you the option of setting the following properties on the cache:less
Cache Size limit (removals use a LRU algorithm)
Wrapping keys in WeakReferences (Strong references used by default for keys)
Wrapping values in either WeakReferences or SoftReferences (Strong references used by default)
Time to expire entires after last access
Time based expiration of entries after being written or updated
Setting a RemovalListener that can recieve events once an entry is removed from the cache
Concurrency Level of the cache (defaults to 4)
CacheBuilder被用來建立cache實例(譯註:是指被cache的實例)。它使用fluent style(譯註:就是.xx().xx().xx()的模式)來建立,使你能夠指定cache的下列的屬性:
The concurrency level option is used to partition the table internally such that updates can occur without contention. The ideal setting would be the maximum number of threads that could potentially access the cache at one time. Here is an example of a possible usage scenario for Guava Cache.
併發度選擇用來在給內部的表作分區(譯註:指cache實現時,在內部存儲條目用的表),使得更新能夠無競爭的進行。最理想的設置是有可能同時訪問這個cache的線程的數目。下面是一個可能使用Guava Cache的場景
public class PersonSearchServiceImpl implements SearchService<List<Person>> { public PersonSearchServiceImpl(SampleLuceneSearcher luceneSearcher, SampleDBService dbService) { this.luceneSearcher = luceneSearcher; this.dbService = dbService; buildCache(); } @Override public List<Person> search(String query) throws Exception { return cache.get(query); } private void buildCache() { cache = CacheBuilder.newBuilder().expireAfterWrite(10, TimeUnit.MINUTES) .maximumSize(1000) .build(new CacheLoader<String, List<Person>>() { @Override public List<Person> load(String queryKey) throws Exception { List<String> ids = luceneSearcher.search(queryKey); return dbService.getPersonsById(ids); } }); } }
In this example, I am setting the cache entries to expire after 10 minutes of being written or updated in the cache, with a maximum amount of 1,000 entires. Note the usage of CacheLoader on line 15.
在這個例子中,我設置cache的條目會在寫入或者更新10分鐘後過時,最大數目數量是1000。注意第15行的CacheLoader的例子
The RemovalListener will receive notification of an item being removed from the cache. These notifications could be from manual invalidations or from a automatic one due to time expiration or garbage collection. The RemovalListener<K,V> parameters can be set to listen for specific type. To receive notifications for any key or value set them to use Object. It should be noted here that a RemovalListener will receive a RemovalNotification<K,V> object that implements the Map.Entry interface. The key or value could be null if either has already been garbage collected. Also the key and value object will be strong references, regardless of the type of references used by the cache.
RemovalListener會在條目被從cache移除之後收到通知。這個通知可能源於手動地使條目失效,或者因爲時間過時或者垃圾回收而自動地移除條目。RemovalListener<K,V>的類型參數能夠被設置以監聽指定的類型。若是要接收任何的kv的通知,把它們設成Object。須要說明的是,RemovalListener會收到一個RemovalNotification<K,V>類型的對象,這個對象實現了Map.Entry接口。若是key或者value被垃圾回收了,那麼key和value可能會爲null.並且key和value對象是是strong reference,無論在cache中的時候的reference的類型。
There is also a very useful class CacheStats that can be retrieved via a call to Cache.stats(). The CacheStats object can give insight into the effectiveness and performance of your cache by providing statistics such as:
有一個很是有用CacheStats類的對象,可使用Cache.status()來獲取。CacheStats對象經過給你下面的統計,能夠給出關於你的cache的效率和性能的洞察。
hit count 命中總數
miss count 未命中總數
total load time 總的加載時間
total requests 總的請求數目
CacheStats provides many other counts in addition to the ones listed above.
除了上邊列出的統計結果,CacheStatus還提供了不少其它的值。
The Guava Cache presents some very compelling functionality. The decision to use a Guava Cache really comes down to the tradeoff between memory availability/usage versus increases in performance. I have added a unit test CacheTest demonstrating the usages discussed here. As alway comments and suggestions are welcomed. Thanks for your time.
GuavaCache提供了一些很是有競爭力的功能。使用Guava Cache源於對可用/使用的內存以及性能的折衷。我添加了一個單元測試來展現這裏討論的使用狀況。像往常同樣,歡迎評論和建議。謝謝你的時間。