java 手写 jvm高性能缓存,键值对存储,队列存储,存储超时设置
1 package com.ws.commons.cache; 2 3 import java.time.LocalDateTime; 4 import java.time.format.DateTimeFormatter; 5 import java.util.ArrayList; 6 import java.util.Collections; 7 import java.util.Iterator; 8 import java.util.LinkedHashMap; 9 import java.util.List; 10 import java.util.Map; 11 import java.util.Map.Entry; 12 import java.util.concurrent.ConcurrentLinkedDeque; 13 import java.util.concurrent.ExecutorService; 14 import java.util.concurrent.Executors; 15 import java.util.concurrent.atomic.AtomicInteger; 16 17 import com.ws.commons.tool.ThreadTool; 18 19 /** 20 * 本地高性能缓存 21 * 22 * @author 尘无尘 23 * 24 */ 25 public class LocalCache { 26 27 private LocalCache() { 28 } 29 30 /** 31 * 缓存实例 32 */ 33 private static final Map<String, Object> INSTANCE = Collections.synchronizedMap(new LinkedHashMap<>()); 34 35 /** 36 * 缓存KEY 存储时间记录 37 */ 38 private static final Map<String, Long> KEY_TIME_INSTANCE = Collections.synchronizedMap(new LinkedHashMap<>()); 39 40 /** 41 * 时间格式化对象 42 */ 43 public static final DateTimeFormatter yyyyMMddHHmmss_FMT = DateTimeFormatter.ofPattern("yyyyMMddHHmmss"); 44 45 /** 46 * 存储最大数据数量,超出该数据量时,删除最新存储的数据 47 */ 48 private static final int MAXCOUNT = 10000; 49 50 /** 51 * 清理缓存线程,防止频繁的缓存清理 创建线程消耗性能 52 */ 53 private static final ExecutorService THREAD_POOL = Executors.newCachedThreadPool(); 54 55 /** 56 * 清理缓存时线程做的标记 57 */ 58 private static final AtomicInteger TREAM_CACHE_FLAG = new AtomicInteger(0); 59 60 /** 61 * 缓存清理 轮询一圈等待时长 62 */ 63 private static final int TRIM_INTERIM = 2000; 64 65 /** 66 * 队列存储,在末尾添加元素 67 * 68 * @param key 69 * @param value 70 * @param outSecond 保存时间(秒),超出时间,被清除 71 */ 72 @SuppressWarnings("unchecked") 73 public static void rightPush(String key, Object value, int outSecond) { 74 ConcurrentLinkedDeque<Object> linkList = (ConcurrentLinkedDeque<Object>) INSTANCE.get(key); 75 if (linkList == null) { 76 linkList = new ConcurrentLinkedDeque<>(); 77 INSTANCE.put(key, linkList); 78 } 79 KEY_TIME_INSTANCE.put(key, 80 Long.parseLong(LocalDateTime.now().plusSeconds(outSecond).format(yyyyMMddHHmmss_FMT))); 81 linkList.offer(value); 82 LocalCache.streamInstance(); 83 } 84 85 /** 86 * 队列存储,在末尾添加元素 87 * 88 * @param key 89 * @param value 90 */ 91 @SuppressWarnings("unchecked") 92 public static void rightPush(String key, Object value) { 93 ConcurrentLinkedDeque<Object> linkList = (ConcurrentLinkedDeque<Object>) INSTANCE.get(key); 94 if (linkList == null) { 95 linkList = new ConcurrentLinkedDeque<>(); 96 INSTANCE.putIfAbsent(key, linkList); 97 } 98 linkList.offer(value); 99 LocalCache.streamInstance(); 100 } 101 102 /** 103 * 队列存储,在开头添加元素 104 * 105 * @param key 106 * @param value 107 */ 108 @SuppressWarnings("unchecked") 109 public static void leftPush(String key, Object value) { 110 ConcurrentLinkedDeque<Object> linkList = (ConcurrentLinkedDeque<Object>) INSTANCE.get(key); 111 if (linkList == null) { 112 linkList = new ConcurrentLinkedDeque<>(); 113 INSTANCE.putIfAbsent(key, linkList); 114 } 115 linkList.offerFirst(value); 116 LocalCache.streamInstance(); 117 } 118 119 /** 120 * 删除队列的最后一个元素 121 * 122 * @param key 123 * @return 124 */ 125 @SuppressWarnings("unchecked") 126 public static <T> T rightPop(String key) { 127 ConcurrentLinkedDeque<Object> linkList = (ConcurrentLinkedDeque<Object>) INSTANCE.get(key); 128 if (linkList == null) { 129 return null; 130 } 131 return (T) linkList.pollLast(); 132 } 133 134 /** 135 * 删除队列的第一个元素 136 * 137 * @param key 138 * @return 139 */ 140 @SuppressWarnings("unchecked") 141 public static <T> T leftPop(String key) { 142 ConcurrentLinkedDeque<Object> linkList = (ConcurrentLinkedDeque<Object>) INSTANCE.get(key); 143 if (linkList == null) { 144 return null; 145 } 146 return (T) linkList.pollFirst(); 147 } 148 149 /** 150 * 151 * @param key 152 * @param value 153 */ 154 public static void put(String key, Object value) { 155 INSTANCE.put(key, value); 156 LocalCache.streamInstance(); 157 } 158 159 /** 160 * 161 * @param key 162 * @param value 163 * @param outSecond 保存时间(秒),超出时间,被清除 164 */ 165 public static void put(String key, Object value, int outSecond) { 166 INSTANCE.put(key, value); 167 KEY_TIME_INSTANCE.put(key, 168 Long.parseLong(LocalDateTime.now().plusSeconds(outSecond).format(yyyyMMddHHmmss_FMT))); 169 LocalCache.streamInstance(); 170 } 171 172 /** 173 * 174 * @param key 175 * @param value 176 * @return 177 */ 178 public static Object putIfAbsent(String key, Object value) { 179 Object result = null; 180 result = INSTANCE.putIfAbsent(key, value); 181 LocalCache.streamInstance(); 182 return result; 183 } 184 185 /** 186 * 187 * @param key 188 * @param value 189 * @param outSecond 保存时间(秒),超出时间,被清除 190 * @return 191 */ 192 public static Object putIfAbsent(String key, Object value, int outSecond) { 193 Object result = null; 194 result = INSTANCE.putIfAbsent(key, value); 195 KEY_TIME_INSTANCE.putIfAbsent(key, 196 Long.parseLong(LocalDateTime.now().plusSeconds(outSecond).format(yyyyMMddHHmmss_FMT))); 197 LocalCache.streamInstance(); 198 return result; 199 } 200 201 /** 202 * 获取缓存 203 * 204 * @param id 205 * @return 206 */ 207 @SuppressWarnings("unchecked") 208 public static <T> T get(String key) { 209 T value = (T) INSTANCE.get(key); 210 if (value == null) { 211 return null; 212 } 213 if (LocalCache.isTimeOut(key)) { 214 INSTANCE.remove(key); 215 KEY_TIME_INSTANCE.remove(key); 216 return null; 217 } else { 218 return value; 219 } 220 } 221 222 /** 223 * 删除并返回 224 * 225 * @param id 226 * @return 227 */ 228 @SuppressWarnings("unchecked") 229 public static <T> T remove(String id) { 230 return (T) INSTANCE.remove(id); 231 } 232 233 /** 234 * 整理缓存:<br> 235 * 整理的缓存的线程只能一个,节约资源开销<br> 236 * TRIM_INTERIM<br> 237 */ 238 private static void streamInstance() { 239 240 if (TREAM_CACHE_FLAG.incrementAndGet() > 1) { 241 return; 242 } 243 THREAD_POOL.execute(() -> { 244 long now = Long.parseLong(LocalDateTime.now().format(yyyyMMddHHmmss_FMT)); 245 do { 246 /* 247 * 1、超时缓存清除 248 */ 249 Iterator<Entry<String, Object>> instanceIt = INSTANCE.entrySet().iterator(); 250 while (instanceIt.hasNext()) { 251 String key = instanceIt.next().getKey(); 252 if (LocalCache.isTimeOut(key, now)) { 253 instanceIt.remove(); 254 KEY_TIME_INSTANCE.remove(key); 255 } 256 } 257 258 /* 259 * 2、 超容量,从首位开始清除 260 */ 261 if (INSTANCE.size() > MAXCOUNT) { 262 List<String> tempList = new ArrayList<>(); 263 for (Entry<String, Object> en : INSTANCE.entrySet()) { 264 tempList.add(en.getKey()); 265 if (INSTANCE.size() - tempList.size() <= MAXCOUNT) { 266 tempList.forEach(e -> { 267 INSTANCE.remove(e); 268 KEY_TIME_INSTANCE.remove(e); 269 }); 270 break; 271 } 272 } 273 } 274 275 ThreadTool.sleep(TRIM_INTERIM); 276 now = Long.valueOf(LocalDateTime.now().format(yyyyMMddHHmmss_FMT)); 277 } while (INSTANCE.size() > 0); 278 TREAM_CACHE_FLAG.set(0); 279 }); 280 } 281 282 /** 283 * 判断key对比当前时间是否超时 284 * 285 * @param key 286 * @return 287 */ 288 private static boolean isTimeOut(String key) { 289 long now = Long.parseLong(LocalDateTime.now().format(yyyyMMddHHmmss_FMT)); 290 return LocalCache.isTimeOut(key, now); 291 } 292 293 /** 294 * 295 * 判断key对比now是否超时 296 * 297 * @param key 298 * @param now 299 * @return 300 */ 301 private static boolean isTimeOut(String key, long now) { 302 Long saveTime = KEY_TIME_INSTANCE.get(key); 303 return saveTime == null || saveTime < now; 304 } 305 }
原文:https://www.cnblogs.com/abab/p/11121773.html