構建高效且可伸縮的結果快取
JAVA併發程式設計實踐
第85頁
環境 JDK1.6(貌似使用1.7編譯會有問題)
第一版 synchronized 控制併發
ExpensiveFunction 模擬一個很費時間的操作.比如資料庫讀取。
這個版本問題很明顯,就是synchronized 限制了併發.
第二版 ConcurrentHashMap替換HashMap
這個版本的問題是,在併發很高的情況下,一旦快取失效,大量的請求會擁塞資料庫的所有執行緒.造成資料庫的間歇性問題.
第三版 Future
這個版本的問題是
if(f==null)是非原子的"先檢查後執行",可能會有多個執行緒同時進入該段程式碼.但是相對於第二版,機率已經大大降低.
最終版本
這個版本還是有一些問題,比如沒有快取失效機制,並且異常的時候沒有將Future從Map中移除.
不過已經說明了很多的用法.
這個while迴圈感覺很精妙
一旦 return f.get()發生ExecutionException異常,程式碼不會退出,而是會再次執行.
第85頁
環境 JDK1.6(貌似使用1.7編譯會有問題)
第一版 synchronized 控制併發
-
import java.math.BigInteger;
-
import java.util.HashMap;
-
import java.util.Map;
-
-
interface Computable<A, V> {
-
V compute(A arg) throws InterruptedException;
-
}
-
-
class ExpensiveFunction implements Computable<String, BigInteger> {
-
@Override
-
public BigInteger compute(String arg) throws InterruptedException {
-
return new BigInteger(arg);
-
}
-
}
-
-
class Memoizer1<A, V> implements Computable<A, V> {
-
private final Map<A, V> cache = new HashMap<A, V>();
-
private final Computable<A, V> c;
-
-
public Memoizer1(Computable<A, V> c) {
-
this.c = c;
-
}
-
-
@Override
-
public synchronized V compute(A arg) throws InterruptedException {
-
V result = cache.get(arg);
-
if (result == null) {
-
result = c.compute(arg);
-
cache.put(arg, result);
-
}
-
return result;
-
-
}
- }
這個版本問題很明顯,就是synchronized 限制了併發.
第二版 ConcurrentHashMap替換HashMap
-
import java.math.BigInteger;
-
import java.util.Map;
-
import java.util.concurrent.ConcurrentHashMap;
-
-
interface Computable<A, V> {
-
V compute(A arg) throws InterruptedException;
-
}
-
-
class ExpensiveFunction implements Computable<String, BigInteger> {
-
@Override
-
public BigInteger compute(String arg) throws InterruptedException {
-
return new BigInteger(arg);
-
}
-
}
-
-
class Memoizer2<A, V> implements Computable<A, V> {
-
private final Map<A, V> cache = new ConcurrentHashMap<A, V>();
-
private final Computable<A, V> c;
-
-
public Memoizer2(Computable<A, V> c) {
-
this.c = c;
-
}
-
-
@Override
-
public V compute(A arg) throws InterruptedException {
-
V result = cache.get(arg);
-
if (result == null) {
-
result = c.compute(arg);
-
cache.put(arg, result);
-
}
-
return result;
-
-
}
- }
第三版 Future
-
import java.math.BigInteger;
-
import java.util.Map;
-
import java.util.concurrent.Callable;
-
import java.util.concurrent.ConcurrentHashMap;
-
import java.util.concurrent.ExecutionException;
-
import java.util.concurrent.Future;
-
import java.util.concurrent.FutureTask;
-
-
interface Computable<A, V> {
-
V compute(final A arg) throws InterruptedException, ExecutionException;
-
}
-
-
class ExpensiveFunction implements Computable<String, BigInteger> {
-
@Override
-
public BigInteger compute(String arg) throws InterruptedException, ExecutionException {
-
return new BigInteger(arg);
-
}
-
}
-
-
class Memoizer3<A, V> implements Computable<A, V> {
-
private final Map<A, Future<V>> cache = new ConcurrentHashMap<A, Future<V>>();
-
private final Computable<A, V> c;
-
-
public Memoizer3(Computable<A, V> c) {
-
this.c = c;
-
}
-
-
@Override
-
public V compute(final A arg) throws InterruptedException, ExecutionException {
-
Future<V> f = cache.get(arg);
-
if (f == null) {
-
Callable<V> eval = new Callable<V>() {
-
-
@Override
-
public V call() throws ExecutionException, InterruptedException {
-
return c.compute(arg);
-
}
-
-
};
-
FutureTask<V> ft = new FutureTask<V>(eval);
-
f = ft;
-
cache.put(arg, ft);
-
ft.run();
-
}
-
return f.get();
-
}
- }
if(f==null)是非原子的"先檢查後執行",可能會有多個執行緒同時進入該段程式碼.但是相對於第二版,機率已經大大降低.
最終版本
-
import java.math.BigInteger;
-
import java.util.Map;
-
import java.util.concurrent.Callable;
-
import java.util.concurrent.ConcurrentHashMap;
-
import java.util.concurrent.ExecutionException;
-
import java.util.concurrent.Future;
-
import java.util.concurrent.FutureTask;
-
-
interface Computable<A, V> {
-
V compute(final A arg) throws InterruptedException;
-
}
-
-
class ExpensiveFunction implements Computable<String, BigInteger> {
-
@Override
-
public BigInteger compute(String arg) throws InterruptedException {
-
return new BigInteger(arg);
-
}
-
}
-
-
class Memoizer3<A, V> implements Computable<A, V> {
-
private final ConcurrentHashMap<A, Future<V>> cache = new ConcurrentHashMap<A, Future<V>>();
-
private final Computable<A, V> c;
-
-
public Memoizer3(Computable<A, V> c) {
-
this.c = c;
-
}
-
-
@Override
-
public V compute(final A arg) throws InterruptedException {
-
while (true) {
-
Future<V> f = cache.get(arg);
-
if (f == null) {
-
Callable<V> eval = new Callable<V>() {
-
public V call() throws InterruptedException {
-
return c.compute(arg);
-
}
-
};
-
-
FutureTask<V> ft = new FutureTask<V>(eval);
-
f = cache.putIfAbsent(arg, ft);
-
if (f == null) {
-
f = ft;
-
ft.run();
-
}
-
}
-
try {
-
return f.get();
-
} catch (ExecutionException e) {
-
e.printStackTrace();
-
}
-
}
-
}
- }
不過已經說明了很多的用法.
這個while迴圈感覺很精妙
一旦 return f.get()發生ExecutionException異常,程式碼不會退出,而是會再次執行.
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/29254281/viewspace-1782226/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 關於記憶體快取的可伸縮性問題記憶體快取
- 基於 HBase 構建可伸縮的分散式事務佇列分散式佇列
- 實戰:構建可伸縮Hadoop叢集的方法步驟Hadoop
- 可伸縮NoSQL資料庫的五條建議SQL資料庫
- Node.js的可伸縮性Node.js
- 大型網站的可伸縮性架構如何設計?網站架構
- 高可用可伸縮架構實用經驗談架構
- 使用Java和Redis構建高效能的快取系統JavaRedis快取
- Java微服務開發指南–使用Docker和Kubernetes構建可伸縮的微服務Java微服務Docker
- 深入探索ArkWeb:構建高效且安全的Web元件Web元件
- 淘寶可伸縮高效能網際網路架構: 果然每一項都很關鍵架構
- 可伸縮聚類演算法綜述(可伸縮聚類演算法開篇)聚類演算法
- oracle result cache 結果集快取的使用Oracle快取
- Twitter如何使用Redis提高可伸縮性Redis
- DDL,DML操作對結果快取的影響快取
- Blitz4j - 可伸縮的日誌框架框架
- [IDS培訓文件]第一章 Informix動態可伸縮體系結構ORM
- PLSQL Language Reference-PL/SQL子程式-PL/SQL函式結果快取-開啟函式結果快取SQL函式快取
- 網站架構的伸縮性設計網站架構
- CSS 可伸縮圓角導航選單CSS
- 可伸縮的微服務告警系統設計指南微服務
- 簡析Uber的可伸縮監控:uMonitor和Neris
- 自定義view之可伸縮的圓弧與扇形View
- input文字框獲取焦點伸縮效果
- 11g新特性之結果集快取快取
- 一個社交App是如何構建高伸縮性的互動式系統APP
- 關於分頁查詢結果的快取問題快取
- jQuery可伸縮搜尋框程式碼例項jQuery
- 基於webpack4[.3+]構建可預測的持久化快取方案Web持久化快取
- 垂直可伸縮的導航選單例項程式碼單例
- 可伸縮性和重/輕量,誰是實用系統的架構主選?架構
- 基於 Raft 構建彈性伸縮的儲存系統的一些實踐Raft
- MySQL:MySQL客戶端快取結果導致OOMMySql客戶端快取OOM
- Oracle11新特性——SQL快取結果集(五)OracleSQL快取
- 11g result cache 結果快取記憶體快取記憶體
- Oracle11新特性——SQL快取結果集(三)OracleSQL快取
- Oracle 11g 的server結果快取result_cache_modeOracleServer快取
- 懸浮在網頁頂部可伸縮層詳解網頁