本地缓存的作用:
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(); } }