本地緩存的作用:
0.基於LinkedHashMap實現LRU
1) 構造LRUMap類,重寫LinkedHashMap中removeEldestEntry方法; 新增元素的時候,會判斷當前map大小是否超過DEFAULT_MAX_CAPACITY,超過則移除map中最老的節點;
2)LinkedHashMap線程不安全,再插入刪除元素時使用顯示讀寫鎖ReentrantReadWriteLock
3) 使用ScheduledExecutorService作為定時器,其具有一個schedule()方法,可以傳入一個Runnable實例,和一個定時時長 => 每次新插入的時候都建立一個schedule,以key為標識,過了指定時間后,進行刪除key,以實現LRU算法

package demo.shaw.common; import java.util.LinkedHashMap; import java.util.Map; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.ThreadFactory; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock; public class LocalCache { private static final Map<String, Object> map; private static final ScheduledExecutorService timerService; //定時器 /** * 默認有效時長 */ private static final long DEFAULT_TIMEOUT = 3600; private static final long SECOND_TIME = 1000; /** * 初始化塊總是在構造器之前執行 * 靜態初始化塊執行的優先級高於非靜態初始化塊,在對象裝載到JVM中時執行一次,僅能初始化類成員變量,即static修飾的數據成員 * 靜態初始化塊是類相關的,系統將在類加載時執行靜態初始化塊,而不是在創建對象時才執行,因此靜態初始化塊總是比非靜態初始化塊先執行 */ static { map = new LRUMap<>(); timerService = new ScheduledThreadPoolExecutor(1, new LocalCache.DaemonThreadFactory()); } /** * 工具類 */ private LocalCache() { } static class LRUMap<K, V> extends LinkedHashMap<K, V> { /** * 默認緩存大小 */ private static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; /** * 默認最大緩存大小 */ private static final int DEFAULT_MAX_CAPACITY = 1 << 30; /** * 默認加載因子 */ private static final float DEFAULT_LOAD_FACTOR = 0.75f; /** * 讀寫鎖 */ private ReadWriteLock readWriteLock = new ReentrantReadWriteLock(); private final Lock rLock = readWriteLock.readLock(); private final Lock wLock = readWriteLock.writeLock(); public LRUMap() { super(DEFAULT_INITIAL_CAPACITY, DEFAULT_LOAD_FACTOR); } public LRUMap(int initialCapacity) { super(initialCapacity, DEFAULT_LOAD_FACTOR); } /** * 需要重寫LinkedHashMap中removeEldestEntry方法; * 新增元素的時候,會判斷當前map大小是否超過DEFAULT_MAX_CAPACITY,超過則移除map中最老的節點; * @param eldest * @return */ protected boolean removeEldestEntry(Map.Entry<K,V> eldest) { return size() > DEFAULT_MAX_CAPACITY; } public V put(K k, V v) { wLock.lock(); try { return super.put(k, v); } finally { wLock.unlock(); } } public V get(String k) { rLock.lock(); try { return super.get(k); } finally { rLock.unlock(); } } public void putAll(Map<? extends K, ? extends V> m) { wLock.lock(); try { super.putAll(m); } finally { wLock.unlock(); } } public V remove(Object k) { wLock.lock(); try { return super.remove(k); } finally { wLock.unlock(); } } public boolean containKey(K k) { rLock.lock(); try { return super.containsKey(k); } finally { rLock.unlock(); } } public int size() { rLock.lock(); try { return super.size(); } finally { rLock.unlock(); } } public void clear() { wLock.lock(); try { super.clear(); } finally { wLock.unlock(); } } } /** * 清除緩存的任務類 */ static class CleanWorkerTask implements Runnable { private String key; public CleanWorkerTask(String key) { this.key = key; } @Override public void run() { LocalCache.remove(key); } } private static final class DaemonThreadFactory implements ThreadFactory { private AtomicInteger atomicInteger = new AtomicInteger(0); @Override public Thread newThread(Runnable runnable) { Thread thread = new Thread(runnable); thread.setName("schedule-pool-Thread-" + atomicInteger.getAndIncrement()); thread.setDaemon(true); return null; } } /** * 增加緩存 */ public static void add(String key, Object value) { map.put(key, value); timerService.schedule(new CleanWorkerTask(key), DEFAULT_TIMEOUT, TimeUnit.MILLISECONDS); } /** * 增加緩存 * @param timeout 有效時長 */ public static void add(String key, Object value, int timeout) { map.put(key, value); timerService.schedule(new CleanWorkerTask(key), timeout * SECOND_TIME, TimeUnit.MILLISECONDS); } public static void putAll(Map<String, Object> m, int timeout) { map.putAll(m); for (String key : m.keySet()) { timerService.schedule(new CleanWorkerTask(key), timeout * SECOND_TIME, TimeUnit.MILLISECONDS); } } /** * 獲取緩存 */ public static Object get(String key) { return map.get(key); } public static boolean containsKey(String key) { return map.containsKey(key); } /** * * @param key */ public static void remove(String key) { map.remove(key); } public static int size() { return map.size(); } }