構建高效且可伸縮的結果快取
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/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- Node.js的可伸縮性Node.js
- 大型網站的可伸縮性架構如何設計?網站架構
- 使用Java和Redis構建高效能的快取系統JavaRedis快取
- 可伸縮聚類演算法綜述(可伸縮聚類演算法開篇)聚類演算法
- 深入探索ArkWeb:構建高效且安全的Web元件Web元件
- CSS 可伸縮圓角導航選單CSS
- 可伸縮的微服務告警系統設計指南微服務
- 簡析Uber的可伸縮監控:uMonitor和Neris
- input文字框獲取焦點伸縮效果
- 基於webpack4[.3+]構建可預測的持久化快取方案Web持久化快取
- 伸縮架構原理也適用於大模型架構大模型
- CSS 小結筆記之伸縮佈局 (flex)CSS筆記Flex
- 探討下如何更好的使用快取 —— Redis快取的特殊用法以及與本地快取一起構建多級快取的實現快取Redis
- Redis 的高效能快取機制的三類問題:快取擊穿、快取雪崩 和 快取穿透Redis快取穿透
- 可複用的快取元件快取元件
- 優雅的構建 Android 專案之磁碟快取(DiskLruCache)Android快取
- CSS-伸縮佈局CSS
- Redis 叢集伸縮原理Redis
- 從SpringBoot構建十萬博文聊聊快取穿透Spring Boot快取穿透
- MySQL:MySQL客戶端快取結果導致OOMMySql客戶端快取OOM
- Dubbo 3.0 前瞻系列:服務發現支援百萬叢集,帶來可伸縮微服務架構微服務架構
- windows NLB+ARR實現Web負載均衡高可用/可伸縮的方法WindowsWeb負載
- 彈性伸縮:高可用架構利器(架構+演算法+思維)架構演算法
- iOS快取的總結iOS快取
- 構建高效的 API 規範API
- Welcome to YARP - 5.壓縮、快取快取
- CSS3 伸縮佈局CSSS3
- 構建高可用性、高效能和可擴充套件的Zabbix Server架構套件Server架構
- 兩欄佈局,左側可伸縮,右側寬度自適應
- 見面會 | 創新工場執行董事王嘉平:高效能可伸縮性區塊鏈系統揭祕!區塊鏈
- Leetcode LRU快取,陣列+結構體實現LeetCode快取陣列結構體
- 支援自動伸縮的消費者模式模式
- 面試總結 —— Redis “快取穿透”、“快取擊穿”、“快取雪崩”面試Redis快取穿透
- mysql group by 取想要的結果MySql
- 讀構建可擴充套件分散式系統:方法與實踐05分散式快取套件分散式快取
- redis自學(37)叢集伸縮Redis
- 彈性佈局(伸縮佈局)
- Knative Autoscaler 自定義彈性伸縮
- Java高併發快取架構,快取雪崩、快取穿透之謎Java快取架構穿透