java 手写 jvm高性能缓存
java 手写 jvm高性能缓存,键值对存储,队列存储,存储超时设置
缓存接口
package com.ws.commons.cache;
import java.util.function.Function;
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);
public <T> T computeIfAbsent(String key, int outSecond, Function<String, Object> mappingFunction);
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);
}
实现类
package com.ws.commons.cache; import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Iterator;
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 java.util.function.Function; import com.googlecode.concurrentlinkedhashmap.ConcurrentLinkedHashMap;
import com.googlecode.concurrentlinkedhashmap.Weighers;
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 int MAXCOUNT = 2000; /**
* 缓存实例
*/
private static final Map<String, Object> INSTANCE =new ConcurrentLinkedHashMap.Builder<String, Object>()
.maximumWeightedCapacity(MAXCOUNT). weigher(Weighers.singleton()).initialCapacity(100).build(); /**
* 缓存KEY 存储时间记录
*/
private static final Map<String, Long> KEY_TIME_INSTANCE = new ConcurrentLinkedHashMap.Builder<String, Long>()
.maximumWeightedCapacity(MAXCOUNT). weigher(Weighers.singleton()).initialCapacity(100).build(); /**
* 时间格式化对象
*/
public static final DateTimeFormatter yyyyMMddHHmmss_FMT = DateTimeFormatter.ofPattern("yyyyMMddHHmmss"); /**
* 清理缓存线程,防止频繁的缓存清理 创建线程消耗性能
*/
private static final ExecutorService THREAD_POOL = Executors.newCachedThreadPool(); /**
* 清理缓存时线程做的锁
*/
private static final AtomicInteger TREAM_CACHE_LOCK = 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 outSecond 保存时间(秒),超出时间,被清除
* @param value
*/
@SuppressWarnings("unchecked")
@Override
public <T>T computeIfAbsent(String key, int outSecond, Function<String, Object> mappingFunction) {
T t=(T) INSTANCE.computeIfAbsent(key, mappingFunction);
KEY_TIME_INSTANCE.putIfAbsent(key,
Long.parseLong(LocalDateTime.now().plusSeconds(outSecond).format(yyyyMMddHHmmss_FMT)));
LocalCache.streamInstance();
return t;
} /**
*
* @param key
* @param value
*/
@Override
public void put(String key, Object value) {
INSTANCE.put(key, value);
} /**
*
* @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_LOCK.incrementAndGet() > 1) {
return;
}
THREAD_POOL.execute(() -> {
long now = Long.parseLong(LocalDateTime.now().format(yyyyMMddHHmmss_FMT));
do {
/*
* 1、超时缓存清除
*/
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);
}
} // /*
// * 2、 超容量,从首位开始清除
// */
// 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_LOCK.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;
}
}
java 手写 jvm高性能缓存的更多相关文章
- java手写多级缓存
多级缓存实现类,时间有限,该类未抽取接口,目前只支持两级缓存:JVM缓存(实现 请查看上一篇:java 手写JVM高性能缓存).redis缓存(在spring 的 redisTemplate 基础实现 ...
- 教你如何使用Java手写一个基于链表的队列
在上一篇博客[教你如何使用Java手写一个基于数组的队列]中已经介绍了队列,以及Java语言中对队列的实现,对队列不是很了解的可以我上一篇文章.那么,现在就直接进入主题吧. 这篇博客主要讲解的是如何使 ...
- Java:手写幼儿园级线程安全LRU缓存X探究影响命中率的因素
最近遇到一个需求,需要频繁访问数据库,但是访问的内容只是 id + 名称 这样的简单键值对. 频繁的访问数据库,网络上和内存上都会给数据库服务器带来不小负担. 于是打算写一个简单的LRU缓存来缓存这样 ...
- 利用Java手写简单的httpserver
前言: 在看完尚学堂JAVA300中讲解如何实现一个最简单的httpserver部分的视频之后, 一.前置知识 1.HTTP协议 当前互联网网页访问主要采用了B/S的模式,既一个浏览器,一个服务器,浏 ...
- 第三节:工厂+反射+配置文件(手写IOC)对缓存进行管理。
一. 章前小节 在前面的两个章节,我们运用依赖倒置原则,分别对 System.Web.Caching.Cache和 System.Runtime.Cacheing两类缓存进行了封装,并形成了ICach ...
- 教你如何使用Java手写一个基于数组实现的队列
一.概述 队列,又称为伫列(queue),是先进先出(FIFO, First-In-First-Out)的线性表.在具体应用中通常用链表或者数组来实现.队列只允许在后端(称为rear)进行插入操作,在 ...
- java手写线程池,完善中
package com.test001.threadpool; import java.util.LinkedList; import java.util.List; import java.util ...
- Java手写简单HashMap一(包括增加,查找,toString,泛型)
@Java 300 学习总结 HashMap底层采用实现采用了哈希表,结合了"数组和链表". 原理如图 一.定义HashMap类. 首先需要定义一个节点来存储数据,构成链表结构. ...
- java手写的动态数组JimisunArray
/** * @Author:jimisun * @Description: * @Date:Created in 22:10 2018-07-18 * @Modified By: */ public ...
随机推荐
- adb shell提示“adb server is out of date.” 解决方法
[问题描述] 1.打开运行:window+R,输入cmd回车 2.使用命令 adb shell 无法登录安卓设备,提示如下: adb server is out of date. killing.. ...
- RabbitMQ的几个常见问题
1. 如何保证消息尽量发送成功? 问题描述: 如果没有启动消费者,重启了RabbitMQ服务,队列和消息都会丢失. 解决方案: 针对这个问题,有以下几个机制可以解决: 生产者确认: 持久化: 手动AC ...
- 通过Socket实现TCP编程(十二)
原文链接:https://www.cnblogs.com/hysum/p/7531529.html Socket通信 : TCP协议是面向对象连接.可靠的.有序的,以字节流的方式发送数据. 基于TCP ...
- Leetcode148-Sort_List
Sort_List 在LeetCode 里面,因为只有归并排序的时间复杂度为O(1),所以快速排序用不了,前面两个都没用直接看最后一个归并排序. 冒泡排序(超时了) public ListNode s ...
- zz 机器学习系统或者SysML&DL笔记
机器学习系统或者SysML&DL笔记(一) Oldpan 2019年5月12日 0条评论 971次阅读 1人点赞 在使用过TVM.TensorRT等优秀的机器学习编译优化系统以及Py ...
- POJ2718Smallest Difference(暴力全排列)
传送门 题目大意:升序输入十进制数 没有重复 分成两个非空集合 每个集合组成一个数(不能有前导零) 求两个数差的最小值. 题解:全排列...我数组从1开始怎么一直WA...还有这个输入值得学习. 代码 ...
- java web开发入门十(idea创建maven SSM项目)基于intellig idea
一.搭建项目骨架 二.配置pom.xml <?xml version="1.0" encoding="UTF-8"?> <project xm ...
- 在 Queue 中 poll()和 remove()有什么区别?
remove() ,如果队列为空的时候,则会抛出异常 而poll()只会返回null
- 100教程-100jc.cn
个人编程笔记网站(持续更新) http://100jc.cn
- SpringBoot第三篇:配置文件详解二
作者:追梦1819 原文:https://www.cnblogs.com/yanfei1819/p/10615605.html 版权声明:本文为博主原创文章,转载请附上博文链接! 前言 本文主要讲 ...