緩存在各種各樣的系統中都非常有用。例如,當一個值的計算或檢索成本很高時,您應該考慮使用緩存。
緩存類似於ConcurrentMap,但不完全相同。最基本的區別是,ConcurrentMap將所有添加到其中的元素持久化,直到它們被顯式刪除。另一方面,緩存通常被配置爲自動收回條目,以限制其內存佔用。在某些情況下,LoadingCache 可能很有用,即使它沒有逐出條目,因爲它是自動加載緩存的。
適用場景
1)使用內存提高數據訪問速度
2)數據訪問頻率比較高
3)數據量不大,且不應該超過你的服務器內存(如果存放大量數據,應該使用Redis或者Memcache)
緩存用例
關於緩存的第一個問題是:是否有一些合理的默認函數來加載或計算與鍵關聯的值?如果是,則應使用緩存加載器。如果不是,或者如果需要重寫默認值,但仍然需要原子“get if absent compute”語義,則應將可調用的傳遞到get調用中。可以使用cache.put直接插入元素,但最好使用自動緩存加載,因爲這樣可以更容易地推斷所有緩存內容之間的一致性。
從緩存加載器
public class GuavaCache {
private LoadingCache<String, GuavaCacheData> cache;
public GuavaCache() {
cache = CacheBuilder.newBuilder()
.maximumSize(1000)
.expireAfterWrite(10, TimeUnit.SECONDS)
.build(new CacheLoader<String, GuavaCacheData>(){
@Override
public GuavaCacheData load(String key) throws ExecutionException {
//獲取數據
try {
//這裏僅僅模擬獲取數據非常慢,不要使用該代碼
Thread.sleep(2000L);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
return new GuavaCacheData(key);
}
});
}
public GuavaCacheData getData(String key) throws ExecutionException {
return cache.get(key);
}
}
查詢LoadingCache的規範方法是使用get(k)方法。這將返回已緩存的值,或者使用緩存的緩存加載器以原子方式將新值加載到緩存中。因爲LoadingCache可能拋出異常,LoadingCache.get(k)拋出ExecutionException。你也可以選擇使用getUnchecked(k),它會把所有異常包裝在UncheckedExecutionException中。
定義Callable方法
使用callable時,可以不定義CacheLoader
public GuavaCacheData getCallableData(String key) throws ExecutionException {
return cache.get(key, new Callable<GuavaCacheData>() {
@Override
public GuavaCacheData call() throws Exception {
//獲取數據
try {
//這裏僅僅模擬獲取數據非常慢,不要使用該代碼
Thread.sleep(3000L);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
return new GuavaCacheData(key);
}
});
}
直接插入緩存
值可以用cache.put(key,value)直接插入到緩存中。這將覆蓋緩存中指定key的數據。