源碼地址: GitHub
使用場景
在Java應用中,對于訪問頻率高,更新少的數據,通常的方案是將這類數據加入緩存中。相對從數據庫中讀取來說,讀緩存效率會有很大提升。
在集群環境下,常用的分布式緩存有Redis
、Memcached
等。但在某些業務場景上,可能不需要去搭建一套復雜的分布式緩存系統,在單機環境下,通常是會希望使用內部的緩存(LocalCache
)。
實現
這里提供了兩種LocalCache
的實現,一種是基于ConcurrentHashMap
實現基本本地緩存,另外一種是基于LinkedHashMap
實現LRU
策略的本地緩存。
基于ConcurrentHashMap的實現
1
2
3
4
|
static { timer = new Timer(); map = new ConcurrentHashMap<>(); } |
以ConcurrentHashMap
作為緩存的存儲結構。因為ConcurrentHashMap
的線程安全的,所以基于此實現的LocalCache
在多線程并發環境的操作是安全的。在JDK1.8
中,ConcurrentHashMap
是支持完全并發讀,這對本地緩存的效率也是一種提升。通過調用ConcurrentHashMap
對map
的操作來實現對緩存的操作。
私有構造函數
1
2
3
|
private LocalCache() { } |
LocalCache
是工具類,通過私有構造函數強化不可實例化的能力。
緩存清除機制
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
/** * 清除緩存任務類 */ static class CleanWorkerTask extends TimerTask { private String key; public CleanWorkerTask(String key) { this .key = key; } public void run() { LocalCache.remove(key); } } |
清理失效緩存是由Timer
類實現的。內部類CleanWorkerTask
繼承于TimerTask
用戶清除緩存。每當新增一個元素的時候,都會調用timer.schedule
加載清除緩存的任務。
基于LinkedHashMap的實現
以LinkedHashMap
作為緩存的存儲結構。主要是通過LinkedHashMap
的按照訪問順序的特性來實現LRU
策略。
LRU
LRU
是Least Recently Used
的縮寫,即最近最久未使用。LRU
緩存將會利用這個算法來淘汰緩存中老的數據元素,從而優化內存空間。
基于LRU策略的map
這里利用LinkedHashMap
來實現基于LRU
策略的map
。通過調用父類LinkedHashMap
的構造函數來實例化map
。參數accessOrder
設置為true
保證其可以實現LRU
策略。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
static class LRUMap<K, V> extends LinkedHashMap<K, V> { ... // 省略部分代碼 public LRUMap( int initialCapacity, float loadFactor) { super (initialCapacity, loadFactor, true ); } ... // 省略部分代碼 /** * 重寫LinkedHashMap中removeEldestEntry方法; * 新增元素的時候,會判斷當前map大小是否超過DEFAULT_MAX_CAPACITY,超過則移除map中最老的節點; * * @param eldest * @return */ protected boolean removeEldestEntry(Map.Entry<K, V> eldest) { return size() > DEFAULT_MAX_CAPACITY; } } |
線程安全
1
2
3
4
5
6
7
8
|
/** * 讀寫鎖 */ private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock(); private final Lock rLock = readWriteLock.readLock(); private final Lock wLock = readWriteLock.writeLock(); |
LinkedHashMap
并不是線程安全,如果不加控制的在多線程環境下使用的話,會有問題。所以在LRUMap
中引入了ReentrantReadWriteLock
讀寫鎖,來控制并發問題。
緩存淘汰機制
1
2
3
|
protected boolean removeEldestEntry(Map.Entry<K, V> eldest) { return size() > DEFAULT_MAX_CAPACITY; } |
此處重寫LinkedHashMap
中removeEldestEntry
方法, 當緩存新增元素的時候,會判斷當前map大小是否超過DEFAULT_MAX_CAPACITY
,超過則移除map中最老的節點。
緩存清除機制
緩存清除機制與ConcurrentHashMap
的實現一致,均是通過timer
實現。
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持服務器之家。
原文鏈接:http://www.jianshu.com/p/4194483127fe#