java 手写 jvm高性能缓存,键值对存储,队列存储,存储超时设置
缓存接口
package com.ws.commons.cache; public interface ICache { void expire(String key, int timeOutSecond); void leftPush(String key, Object value); void rightPush(String key, Object value); void rightPush(String key, Object value, int timeOutSecond); <T> T rightPop(String key); <T> T leftPop(String key); void put(String key, Object value); void put(String key, Object value, int timeOutSecond); boolean putIfAbsent(String key, Object value); boolean putIfAbsent(String key, Object value, int timeOutSecond); <T> T get(String key); boolean hasKey(String key); void remove(String key); <T> T removeAndGet(String key); }
实现类
package com.ws.commons.cache; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.concurrent.ConcurrentLinkedDeque; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.atomic.AtomicInteger; import com.ws.commons.tool.ThreadTool; /** * 本地高性能缓存 * * @author 尘无尘 * */ public class LocalCache implements ICache { private static LocalCache staticInstance; public static LocalCache instance() { if (staticInstance != null) { return staticInstance; } else { synchronized (LocalCache.class) { if (staticInstance != null) { return staticInstance; } staticInstance = new LocalCache(); return staticInstance; } } } private LocalCache() { } /** * 缓存实例 */ private static final Map<String, Object> INSTANCE = Collections.synchronizedMap(new LinkedHashMap<>()); /** * 缓存KEY 存储时间记录 */ private static final Map<String, Long> KEY_TIME_INSTANCE = Collections.synchronizedMap(new LinkedHashMap<>()); /** * 时间格式化对象 */ public static final DateTimeFormatter yyyyMMddHHmmss_FMT = DateTimeFormatter.ofPattern("yyyyMMddHHmmss"); /** * 存储最大数据数量,超出该数据量时,删除最新存储的数据 */ private static final int MAXCOUNT = 10000; /** * 清理缓存线程,防止频繁的缓存清理 创建线程消耗性能 */ private static final ExecutorService THREAD_POOL = Executors.newCachedThreadPool(); /** * 清理缓存时线程做的标记 */ private static final AtomicInteger TREAM_CACHE_FLAG = new AtomicInteger(0); /** * 缓存清理 轮询一圈等待时长 */ private static final int TRIM_INTERIM = 2000; /** * 队列存储,在末尾添加元素 * * @param key * @param value * @param outSecond 保存时间(秒),超出时间,被清除 */ @SuppressWarnings("unchecked") @Override public void rightPush(String key, Object value, int outSecond) { ConcurrentLinkedDeque<Object> linkList = (ConcurrentLinkedDeque<Object>) INSTANCE.get(key); if (linkList == null) { linkList = new ConcurrentLinkedDeque<>(); INSTANCE.put(key, linkList); } KEY_TIME_INSTANCE.put(key, Long.parseLong(LocalDateTime.now().plusSeconds(outSecond).format(yyyyMMddHHmmss_FMT))); linkList.offer(value); LocalCache.streamInstance(); } /** * 队列存储,在末尾添加元素 * * @param key * @param value */ @SuppressWarnings("unchecked") @Override public void rightPush(String key, Object value) { ConcurrentLinkedDeque<Object> linkList = (ConcurrentLinkedDeque<Object>) INSTANCE.get(key); if (linkList == null) { linkList = new ConcurrentLinkedDeque<>(); INSTANCE.putIfAbsent(key, linkList); } linkList.offer(value); LocalCache.streamInstance(); } /** * 队列存储,在开头添加元素 * * @param key * @param value */ @SuppressWarnings("unchecked") @Override public void leftPush(String key, Object value) { ConcurrentLinkedDeque<Object> linkList = (ConcurrentLinkedDeque<Object>) INSTANCE.get(key); if (linkList == null) { linkList = new ConcurrentLinkedDeque<>(); INSTANCE.putIfAbsent(key, linkList); } linkList.offerFirst(value); LocalCache.streamInstance(); } /** * 删除队列的最后一个元素 * * @param key * @return */ @SuppressWarnings("unchecked") @Override public <T> T rightPop(String key) { ConcurrentLinkedDeque<Object> linkList = (ConcurrentLinkedDeque<Object>) INSTANCE.get(key); if (linkList == null) { return null; } return (T) linkList.pollLast(); } /** * 删除队列的第一个元素 * * @param key * @return */ @SuppressWarnings("unchecked") @Override public <T> T leftPop(String key) { ConcurrentLinkedDeque<Object> linkList = (ConcurrentLinkedDeque<Object>) INSTANCE.get(key); if (linkList == null) { return null; } return (T) linkList.pollFirst(); } /** * * @param key * @param value */ @Override public void put(String key, Object value) { INSTANCE.put(key, value); LocalCache.streamInstance(); } /** * * @param key * @param value * @param outSecond 保存时间(秒),超出时间,被清除 */ @Override public void put(String key, Object value, int outSecond) { INSTANCE.put(key, value); KEY_TIME_INSTANCE.put(key, Long.parseLong(LocalDateTime.now().plusSeconds(outSecond).format(yyyyMMddHHmmss_FMT))); LocalCache.streamInstance(); } /** * * @param key * @param value * @return */ @Override public boolean putIfAbsent(String key, Object value) { Object result = null; result = INSTANCE.putIfAbsent(key, value); LocalCache.streamInstance(); return result == null; } /** * * @param key * @param value * @param outSecond 保存时间(秒),超出时间,被清除 * @return */ @Override public boolean putIfAbsent(String key, Object value, int outTimeSecond) { Object result = null; result = INSTANCE.putIfAbsent(key, value); KEY_TIME_INSTANCE.putIfAbsent(key, Long.parseLong(LocalDateTime.now().plusSeconds(outTimeSecond).format(yyyyMMddHHmmss_FMT))); LocalCache.streamInstance(); return result == null; } /** * 获取缓存 * * @param key * @return */ @SuppressWarnings("unchecked") @Override public <T> T get(String key) { T value = (T) INSTANCE.get(key); if (value == null) { return null; } if (LocalCache.isTimeOut(key)) { INSTANCE.remove(key); KEY_TIME_INSTANCE.remove(key); return null; } else { return value; } } @Override public void expire(String key, int timeOutSecond) { KEY_TIME_INSTANCE.put(key, Long.parseLong(LocalDateTime.now().plusSeconds(timeOutSecond).format(yyyyMMddHHmmss_FMT))); } /** * 是否含有 * * @param key * @return */ @Override public boolean hasKey(String key) { return INSTANCE.containsKey(key); } /** * 删除 * * @param id * @return */ @Override public void remove(String key) { INSTANCE.remove(key); } /** * 删除并返回 * * @param id * @return */ @SuppressWarnings("unchecked") @Override public <T> T removeAndGet(String key) { return (T) INSTANCE.remove(key); } /** * 整理缓存:<br> * 整理的缓存的线程只能一个,节约资源开销<br> * TRIM_INTERIM<br> */ private static void streamInstance() { if (TREAM_CACHE_FLAG.incrementAndGet() > 1) { return; } THREAD_POOL.execute(() -> { long now = Long.parseLong(LocalDateTime.now().format(yyyyMMddHHmmss_FMT)); do { /* * 1、超时缓存清除 */ Iterator<Entry<String, Object>> instanceIt = INSTANCE.entrySet().iterator(); while (instanceIt.hasNext()) { String key = instanceIt.next().getKey(); if (LocalCache.isTimeOut(key, now)) { instanceIt.remove(); KEY_TIME_INSTANCE.remove(key); } } /* * 2、 超容量,从首位开始清除 */ if (INSTANCE.size() > MAXCOUNT) { List<String> tempList = new ArrayList<>(); for (Entry<String, Object> en : INSTANCE.entrySet()) { tempList.add(en.getKey()); if (INSTANCE.size() - tempList.size() <= MAXCOUNT) { tempList.forEach(e -> { INSTANCE.remove(e); KEY_TIME_INSTANCE.remove(e); }); break; } } } ThreadTool.sleep(TRIM_INTERIM); now = Long.valueOf(LocalDateTime.now().format(yyyyMMddHHmmss_FMT)); } while (!INSTANCE.isEmpty()); TREAM_CACHE_FLAG.set(0); }); } /** * 判断key对比当前时间是否超时 * * @param key * @return */ private static boolean isTimeOut(String key) { long now = Long.parseLong(LocalDateTime.now().format(yyyyMMddHHmmss_FMT)); return LocalCache.isTimeOut(key, now); } /** * * 判断key对比now是否超时 * * @param key * @param now * @return */ private static boolean isTimeOut(String key, long now) { Long saveTime = KEY_TIME_INSTANCE.get(key); return saveTime == null || saveTime < now; } }