1. 程式人生 > >收藏系列之Java快取

收藏系列之Java快取

原github地址: Java-ConcurrentHashMap實現快取,(快取數量,過期時間,過期快取清理)


大佬是下面這位,先儲存一份程式碼,(●’◡’●)
Java-ConcurrentHashMap(快取數量,過期時間,過期快取清理)


原封不動copy一份儲存

package cn.yan.study.utils.cache;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.*;
import java.util.concurrent.*;

/**
 * Created
 * User  wankunYan
 * Date  2018/6/26
 * Time  20:32
 */
public class ConcurrentHashMapCacheUtils { private static Logger LOGGER = LoggerFactory.getLogger(ConcurrentHashMapCacheUtils.class); /** * 快取最大個數 */ private static final Integer CACHE_MAX_NUMBER = 100; /** * 當前快取個數 */ private static Integer CURRENT_SIZE = 0; /** * 時間一分鐘 */
static Long ONE_MINUTE = 1 * 60 * 1000L; /** * 快取物件 */ private static final Map<String, CacheObj> CACHE_OBJECT_MAP = new ConcurrentHashMap<>(); /** * 這個記錄了快取使用的最後一次的記錄,最近使用的在最前面 */ private static final List<String> CACHE_USE_LOG_LIST = new LinkedList
<>(); /** * 清理過期快取是否在執行 */ private static Boolean CLEAN_THREAD_IS_RUN = false; // /** // * 清理執行緒的 // */ // private static ExecutorService executor = Executors.newSingleThreadExecutor(); /** * 設定快取 */ public static void setCache(String cacheKey, Object cacheValue, long cacheTime) { Long ttlTime = null; if (cacheTime <= 0L) { if (cacheTime == -1L) { ttlTime = -1L; } else { return; } } checkSize(); saveCacheUseLog(cacheKey); CURRENT_SIZE = CURRENT_SIZE + 1; if (ttlTime == null) { ttlTime = System.currentTimeMillis() + cacheTime; } CacheObj cacheObj = new CacheObj(cacheValue, ttlTime); CACHE_OBJECT_MAP.put(cacheKey, cacheObj); LOGGER.info("have set key :" + cacheKey); } /** * 設定快取 */ public static void setCache(String cacheKey, Object cacheValue) { setCache(cacheKey, cacheValue, -1L); } /** * 獲取快取 */ public static Object getCache(String cacheKey) { startCleanThread(); if (checkCache(cacheKey)) { saveCacheUseLog(cacheKey); return CACHE_OBJECT_MAP.get(cacheKey).getCacheValue(); } return null; } public static boolean isExist(String cacheKey) { return checkCache(cacheKey); } /** * 刪除所有快取 */ public static void clear() { LOGGER.info("have clean all key !"); CACHE_OBJECT_MAP.clear(); CURRENT_SIZE = 0; } /** * 刪除某個快取 */ public static void deleteCache(String cacheKey) { Object cacheValue = CACHE_OBJECT_MAP.remove(cacheKey); if (cacheValue != null) { LOGGER.info("have delete key :" + cacheKey); CURRENT_SIZE = CURRENT_SIZE - 1; } } /** * 判斷快取在不在,過沒過期 */ private static boolean checkCache(String cacheKey) { CacheObj cacheObj = CACHE_OBJECT_MAP.get(cacheKey); if (cacheObj == null) { return false; } if (cacheObj.getTtlTime() == -1L) { return true; } if (cacheObj.getTtlTime() < System.currentTimeMillis()) { deleteCache(cacheKey); return false; } return true; } /** * 刪除最近最久未使用的快取 */ private static void deleteLRU() { LOGGER.info("delete Least recently used run!"); String cacheKey = CACHE_USE_LOG_LIST.remove(CACHE_USE_LOG_LIST.size() - 1); deleteCache(cacheKey); } /** * 刪除過期的快取 */ static void deleteTimeOut() { LOGGER.info("delete time out run!"); List<String> deleteKeyList = new LinkedList<>(); for(Map.Entry<String, CacheObj> entry : CACHE_OBJECT_MAP.entrySet()) { if (entry.getValue().getTtlTime() < System.currentTimeMillis() && entry.getValue().getTtlTime() != -1L) { deleteKeyList.add(entry.getKey()); } } for (String deleteKey : deleteKeyList) { deleteCache(deleteKey); } LOGGER.info("delete cache count is :" + deleteKeyList.size()); } /** * 檢查大小 * 噹噹前大小如果已經達到最大大小 * 首先刪除過期快取,如果過期快取刪除過後還是達到最大快取數目 * 刪除最久未使用快取 */ private static void checkSize() { if (CURRENT_SIZE >= CACHE_MAX_NUMBER) { deleteTimeOut(); } if (CURRENT_SIZE >= CACHE_MAX_NUMBER) { deleteLRU(); } } /** * 儲存快取的使用記錄 */ private static synchronized void saveCacheUseLog(String cacheKey) { CACHE_USE_LOG_LIST.remove(cacheKey); CACHE_USE_LOG_LIST.add(0,cacheKey); } /** * 設定清理執行緒的執行狀態為正在執行 */ static void setCleanThreadRun() { CLEAN_THREAD_IS_RUN = true; } /** * 開啟清理過期快取的執行緒 */ private static void startCleanThread() { if (!CLEAN_THREAD_IS_RUN) { new Thread(new CleanTimeOutThread()).start(); // executor.submit(new CleanTimeOutThread()); } } public static void showUtilsInfo() { System.out.println("clean time out cache is run :" + CLEAN_THREAD_IS_RUN); System.out.println("cache max count is :" + CACHE_MAX_NUMBER); System.out.println("cache current count is :" + CURRENT_SIZE); System.out.println("cache object map is :" + CACHE_OBJECT_MAP.toString()); System.out.println("cache use log list is :" + CACHE_USE_LOG_LIST.toString()); } public static void main(String[] args) { for (int i = 0; i < 100; i++) { try { Thread.sleep(2 * 1000L); } catch (InterruptedException e) { e.printStackTrace(); } ConcurrentHashMapCacheUtils.setCache("my_cache_key_" + i, i, 60*1000); } for (int i = 0; i < 100; i++) { if (i > 10) { ConcurrentHashMapCacheUtils.getCache("test"); } try { Thread.sleep(2 * 1000L); } catch (InterruptedException e) { e.printStackTrace(); } ConcurrentHashMapCacheUtils.showUtilsInfo(); } } } class CacheObj { /** * 快取物件 */ private Object CacheValue; /** * 快取過期時間 */ private Long ttlTime; CacheObj(Object cacheValue, Long ttlTime) { CacheValue = cacheValue; this.ttlTime = ttlTime; } Object getCacheValue() { return CacheValue; } Long getTtlTime() { return ttlTime; } @Override public String toString() { return "CacheObj{" + "CacheValue=" + CacheValue + ", ttlTime=" + ttlTime + '}'; } } /** * 每一分鐘清理一次過期快取 */ class CleanTimeOutThread implements Runnable{ @Override public void run() { ConcurrentHashMapCacheUtils.setCleanThreadRun(); while (true) { System.out.println("clean thread run "); ConcurrentHashMapCacheUtils.deleteTimeOut(); try { Thread.sleep(ConcurrentHashMapCacheUtils.ONE_MINUTE); } catch (InterruptedException e) { e.printStackTrace(); } } } }