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 ...
随机推荐
- ant+jmeter+jenkins自动环境搭建
一.安装前准备 1.JDK:jdk-8u131-windows-x64 2.jmeter工具:apache-jmeter-5.1.1 3.ANT工具:apache-ant-1.10.3 4.jenki ...
- Rust中的模块及私有性控制
好像没有其它语言的private, protected关键字,应了一个public关键字. mod plant { pub struct Vegetable { pub name: String, _ ...
- 201871010110-李华《面向对象程序设计(java)》第十六周学习总结
博文正文开头格式:(2分) 项目 内容 这个作业属于哪个课程 https://www.cnblogs.com/nwnu-daizh/ 这个作业的要求在哪里 https://www.cnblogs.co ...
- 201871010132--张潇潇--《面向对象程序设计(Java)》第十一周学习总结
博文正文开头格式:(2分) 项目 内容 这个作业属于哪个课程 https://www.cnblogs.com/nwnu-daizh/ 这个作业的要求在哪里 https://www.cnblogs.co ...
- 【转载】Innodb中的事务隔离级别和锁的关系
前言 我们都知道事务的几种性质,数据库为了维护这些性质,尤其是一致性和隔离性,一般使用加锁这种方式.同时数据库又是个高并发的应用,同一时间会有大量的并发访问,如果加锁过度,会极大的降低并发处理能力.所 ...
- JAVA并发-ReentrantReadWriteLock
简介 读写锁维护着一对锁,一个读锁和一个写锁.通过分离读锁和写锁,使得并发性比一般的排他锁有了较大的提升:在同一时间可以允许多个读线程同时访问,但是在写线程访问时,所有读线程和写线程都会被阻塞. 读写 ...
- (translation.E004) You have provided a value for the LANGUAGE_CODE setting that is not in the LANGUAGES setting.
django3.0开始LANGUAGE_CODE前面必须配相应的LANGUAGES配置如下: from django.utils.translation import gettext_lazy as ...
- openlayers上添加点击事件
有很多场景会有这个需求,就是我绘制了图标,点击图标需要展示一些对应的信息 openlayer的事件主要是通过监听来完成的,你所有的icon的点击事件都是可以通过监听map的点击事件来处理对应的逻辑的 ...
- echarts 中 柱图 、折线图、柱图层叠
app.title = '折柱混合'; option = { tooltip: { trigger: 'axis', axisPointer: { type: 'cross', crossStyle: ...
- 第02组 Beta冲刺(1/4)
队名:十一个憨批 组长博客 作业博客 组长黄智 过去两天完成的任务:了解整个游戏的流程 GitHub签入记录 接下来的计划:继续完成游戏 还剩下哪些任务:完成游戏 燃尽图 遇到的困难:没有美术比较好的 ...