java 手寫 jvm高性能緩存,鍵值對存儲,隊列存儲,存儲超時設置java
緩存接口緩存
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); }
實現類jvm
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 { /* * 一、超時緩存清除 */ 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); } } /* * 二、 超容量,從首位開始清除 */ 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; } }