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 }
java 手写 jvm高性能缓存相关推荐
- 大牛程序员用Java手写JVM:刚好够运行 HelloWorld
专注于Java领域优质技术号,欢迎关注 作者:老曹撸代码 1. 前言 没错这又是一篇介绍 JVM 的文章,这类文章网上已经很多,不同角度.不同深度.不同广度,也都不乏优秀的.为什么还要来一篇?首先对于 ...
- 【手写JVM专栏】一、带你用Java实现JVM-开篇
hello,小伙伴们好,我是江湖人送外号[道格牙]的子牙老师. 手写JVM小班一期已经结束了,二期的课也备得差不多了,现在稍微有点时间了,准备给大家出套教程:用Java带你手写JVM. 因为我的手写J ...
- Java 手写一个SQL分页
Java手写一个类似PageHelper的分页SQL 目前分页插件众所周知的莫过于和mybatis完美融合的PageHelper了,简单两行代码就实现了sql分页,配合PageInfo类,将数据总数量 ...
- Java手写线程池-第一代(原创)
个人简介 作者是一个来自河源的大三在校生,以下笔记都是作者自学之路的一些浅薄经验,如有错误请指正,将来会不断的完善笔记,帮助更多的Java爱好者入门. 文章目录 个人简介 Java手写线程池(第一代) ...
- Java 手写签字去除背景 背景透明
Java 手写签字去除背景 背景透明 /*** 白底照片去除白底 形成透明底图片* @param file 需要去除背景的图片* @param Path 去除背景后保存图片的路径* @return t ...
- java手写实现BST
难易程度:★★★ 重要性:★★★★★ 今日头条的面试中有过要求:手写实现BST import java.util.*;public class MyBSTImpl {// BST中的节点TreeNod ...
- 纯jsp实现评论功能_自己实现的java手写tomcat
这是一个java写的模拟tomcat工作原理的demo,是一个极简的tomcat服务器,也是我们培训班(邦邦IT教育)的讲义,是整个j2ee培训的精髓,理解了这个demo其实后面的很多东西都是可以自学 ...
- Java手写HashSet
一:引言 HashSet类继承于 Set接口 其方法均可被直接调用,不用手写,本篇敲的码是为了熟悉底层原理,HashMap的特点:无序,无重复.其底层用的也是map<key,value>容 ...
- Java手写Hashmap(HashMap的基本用法)
一:引言 HashMap是Map的实现类,其方法都可以继承Map,不用手写,本篇只是为了了解底层代码和复习java基础敲得码 二:上码 package cn.wyj.two;public class ...
最新文章
- javascript Windows对象(BOM)
- 双拼输入法键位图_谈谈小鹤双拼入门(1)
- 通过一个简单的例子,了解如何单步调试 Cypress 代码
- DotLiquid模板引擎简介
- 搭建github服务器_搭建一个属于自己的公网博客
- 安卓团课快进_青年大学习网上主题团课第十季第七期答案
- 点击按钮刷新_Chrome扩展推荐:抢票太累?后台监视网页,页面自动刷新和提醒...
- WebLogic UniversalExtractor反序列化漏洞(CVE-2020-14645)的复现和分析
- STL模板之vector与sort的使用
- .Net 读取xml
- 数据--第20课-递归的应用实战二
- java jaas_JAAS(auth和rbac哪个好)
- 论文精读——基于演化动力学的复杂网络中带阈值雪堆博弈模型研究
- mt管理器小白破解之路-基础篇第一课
- 微信小程序-2-微信开发者工具介绍
- word文档中实现目录索引中标题加粗,前导符和页码不加粗
- 2022年8种高级威胁预测出炉、FBI就零日漏洞发出警报|11月22日全球网络安全热点
- 成分句法分析与依存句法分析
- 最小生成树算法之Kruskal算法
- 四阶幻方c语言编程,13年 第四届 蓝桥杯C语言C组 第4题 幻方填空
热门文章
- php导出csv文件乱码问题解决方法
- jquery user interface
- redis——redis简介及基本交互方法
- E: Some index files failed to download. They have been ignored, or old ones used instead.解决方案
- 机器学习速成课程 | 练习 | Google Development——编程练习:特征集
- SpringBoot—@ComponentScan注解过滤排除某个类
- linux 命令行使用wget下载百度云资源
- Ubuntu 16.04 开机自动锁定数字键盘
- Ubuntu 16.04 安装phpmyadmin以及注意事项
- 公司的年度汇报怎么写 年底述职报告写法