Guava是一種基於開源的Java庫,其中包含谷歌正在由他們不少項目使用的不少核心庫。java
這個庫是爲了方便編碼,並減小編碼錯誤。git
這個庫提供用於集合,緩存,支持原語,併發性,常見註解,字符串處理,I/O和驗證的實用方法。github
1 消耗一些內存空間來提高速度;編程
2 緩存中存放的數據總量不會超出內存容量。緩存
(Guava Cache是單個應用運行時的本地緩存,不把數據存放到文件或外部服務器(Memcached, Redis))服務器
數據結構:ConcurrentHash (The returned cache is implemented as a hash table with similar performance characteristics to ConcurrentHashMap
.)數據結構
主要特性(詳見下面的相關連接):併發
1 自動加載app
2 回收策略:yii
2.1 基於容量
2.2 基於存活時間
2.3 基於權重
2.4 基於引用
3 移除監聽器
4 緩存訪問統計
主要接口:CacheBuilder, LoadingCache, CacheStats
使用示例:
public class CacheProTest { LoadingCache<Long, Person> cache; private int cacheTimeoutSeconds = 10; // 10秒 Integer counter = 1; @Before public void initialize() { System.out.println("初始化"); cache = CacheBuilder.newBuilder() /* 回收策略:基於容量(least-recently-used eviction when a maximum size is exceeded) */ .maximumSize(10) // .initialCapacity(initialCapacity) /* 回收策略:基於存活時間(time-based expiration of entries, measured since last access or last write) */ .expireAfterWrite(cacheTimeoutSeconds, TimeUnit.SECONDS) // .expireAfterAccess(duration, unit) // .refreshAfterWrite(duration, unit) /* 回收策略:基於權重 */ // .maximumWeight(maximumWeight) // .weigher(weigher) /* 回收策略:基於引用(keys automatically wrapped in weak references, values automatically wrapped in weak or soft references)*/ // .weakKeys() // .weakValues() // .softValues() // 設置併發數爲5,即同一時間最多隻能有5個線程往cache執行寫入操做 // .concurrencyLevel(concurrencyLevel) /* 緩存訪問統計(accumulation of cache access statistics) */ .recordStats() /* 移除監聽器(notification of evicted (or otherwise removed) entries) */ // .removalListener(listener) .build(new CacheLoader<Long, Person>() { /* 自動加載(automatic loading of entries into the cache) */ @Override public Person load(Long id) throws Exception { System.out.println("獲取值, id=" + id); // 調用接口獲取值 Person p = new Person(); p.setId(id); p.setName("name" + counter.toString()); counter++; return p; } }); } @Test public void test1() { try { /* 獲值 */ // ConcurrentMap<Long, Person> asMap = cache.asMap(); // cache.get(key); // // cache.getAll(keys); // cache.getIfPresent(key); // cache.getAllPresent(keys); // cache.size(); /* 存值 */ // cache.put(key, value); // cache.putAll(m); // Map<? extends K, ? extends V> m /* 移除/刪除 */ // cache.refresh(key); // cache.invalidate(key); // cache.invalidateAll(); // cache.invalidateAll(keys); // cache.cleanUp(); /* 緩存訪問統計 */ CacheStats stats = cache.stats(); stats.averageLoadPenalty(); stats.evictionCount(); stats.hitCount(); stats.hitRate(); stats.loadCount(); stats.loadExceptionCount(); stats.loadExceptionRate(); stats.loadSuccessCount(); stats.missCount(); stats.missRate(); stats.requestCount(); stats.totalLoadTime(); } catch (Exception e) { e.printStackTrace(); } } @Test public void test2() { try { Long id = 1L; Person person1 = cache.get(id); Thread.sleep(3L * 1000L); Person person2 = cache.get(id); Thread.sleep(11L * 1000L); Person person3 = cache.get(id); System.out.println(person1); System.out.println(person2); System.out.println(person3); } catch (Exception e) { e.printStackTrace(); } } } class Person implements Serializable { private static final long serialVersionUID = 1L; private Long id; private String name; public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public String toString() { return JSON.toJSONString(this); } }
1 瞭解LoadingCache.refresh
正如LoadingCache.refresh(K)所聲明,刷新表示爲鍵加載新值,這個過程能夠是異步的。
在刷新操做進行時,緩存仍然能夠向其餘線程返回舊值,而不像回收操做,讀緩存的線程必須等待新值加載完成。
若是刷新過程拋出異常,緩存將保留舊值,而異常會在記錄到日誌後被丟棄[swallowed]。
重載CacheLoader.reload(K, V)能夠擴展刷新時的行爲,這個方法容許開發者在計算新值時使用舊的值。
2 瞭解 清理時機
使用CacheBuilder構建的緩存不會"自動"執行清理和回收工做,也不會在某個緩存項過時後立刻清理,也沒有諸如此類的清理機制。
它會在寫操做時順帶作少許的維護工做,或者偶爾在讀操做時作——若是寫操做實在太少的話。
所以使用LoadingCache.size() 必定要關注這個點。