java 手写 jvm高性能缓存

java 手写 jvm高性能缓存,键值对存储,队列存储,存储超时设置

缓存接口

 1 package com.ws.commons.cache;
 2 
 3 import java.util.function.Function;
 4 
 5 public interface ICache {
 6 
 7     void expire(String key, int timeOutSecond);
 8 
 9     void leftPush(String key, Object value);
10 
11     void rightPush(String key, Object value);
12 
13     void rightPush(String key, Object value, int timeOutSecond);
14 
15     <T> T rightPop(String key);
16 
17     <T> T leftPop(String key);
18 
19     public <T> T computeIfAbsent(String key, int outSecond, Function<String, Object> mappingFunction);
20 
21     void put(String key, Object value);
22 
23     void put(String key, Object value, int timeOutSecond);
24 
25     boolean putIfAbsent(String key, Object value);
26 
27     boolean putIfAbsent(String key, Object value, int timeOutSecond);
28 
29     <T> T get(String key);
30 
31     boolean hasKey(String key);
32 
33     void remove(String key);
34 
35     <T> T removeAndGet(String key);
36 }
View Code

实现类

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