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高性能缓存的更多相关文章

  1. java手写多级缓存

    多级缓存实现类,时间有限,该类未抽取接口,目前只支持两级缓存:JVM缓存(实现 请查看上一篇:java 手写JVM高性能缓存).redis缓存(在spring 的 redisTemplate 基础实现 ...

  2. 教你如何使用Java手写一个基于链表的队列

    在上一篇博客[教你如何使用Java手写一个基于数组的队列]中已经介绍了队列,以及Java语言中对队列的实现,对队列不是很了解的可以我上一篇文章.那么,现在就直接进入主题吧. 这篇博客主要讲解的是如何使 ...

  3. Java:手写幼儿园级线程安全LRU缓存X探究影响命中率的因素

    最近遇到一个需求,需要频繁访问数据库,但是访问的内容只是 id + 名称 这样的简单键值对. 频繁的访问数据库,网络上和内存上都会给数据库服务器带来不小负担. 于是打算写一个简单的LRU缓存来缓存这样 ...

  4. 利用Java手写简单的httpserver

    前言: 在看完尚学堂JAVA300中讲解如何实现一个最简单的httpserver部分的视频之后, 一.前置知识 1.HTTP协议 当前互联网网页访问主要采用了B/S的模式,既一个浏览器,一个服务器,浏 ...

  5. 第三节:工厂+反射+配置文件(手写IOC)对缓存进行管理。

    一. 章前小节 在前面的两个章节,我们运用依赖倒置原则,分别对 System.Web.Caching.Cache和 System.Runtime.Cacheing两类缓存进行了封装,并形成了ICach ...

  6. 教你如何使用Java手写一个基于数组实现的队列

    一.概述 队列,又称为伫列(queue),是先进先出(FIFO, First-In-First-Out)的线性表.在具体应用中通常用链表或者数组来实现.队列只允许在后端(称为rear)进行插入操作,在 ...

  7. java手写线程池,完善中

    package com.test001.threadpool; import java.util.LinkedList; import java.util.List; import java.util ...

  8. Java手写简单HashMap一(包括增加,查找,toString,泛型)

    @Java 300 学习总结 HashMap底层采用实现采用了哈希表,结合了"数组和链表". 原理如图 一.定义HashMap类. 首先需要定义一个节点来存储数据,构成链表结构. ...

  9. java手写的动态数组JimisunArray

    /** * @Author:jimisun * @Description: * @Date:Created in 22:10 2018-07-18 * @Modified By: */ public ...

随机推荐

  1. 爬虫---Beautiful Soup 反反爬虫事例

    前两章简单的讲了Beautiful Soup的用法,在爬虫的过程中相信都遇到过一些反爬虫,如何跳过这些反爬虫呢?今天通过知乎网写一个简单的反爬中 什么是反爬虫 简单的说就是使用任何技术手段,阻止别人批 ...

  2. Windows 局域网内共享

    前言 在局域网内,其它成员无需密码就可以访问某台计算机共享的某个磁盘或某个文件夹. 本文记录几个关键点, 共享端:需要共享的计算机 用户端:从共享计算机读取文件的计算机 共享端 开启guest用户 1 ...

  3. 201871010126 王亚涛 《面向对象程序设计JAVA》第十四周学习总结

    内容 这个作业属于哪个课程 https://www.cnblogs.com/nwnu-daizh/ 这个作业的要求在哪里 https://www.cnblogs.com/nwnu-daizh/p/11 ...

  4. 201871010124--王生涛--《面向对象程序设计(java)》第十二周学习总结

    博文正文开头格式: 项目 内容 这个作业属于哪个课程 https://www.cnblogs.com/nwnu-daizh/ 这个作业的要求在哪里 https://www.cnblogs.com/nw ...

  5. CF1045B Space Isaac

    原题链接 DOWNLOAD AS PDF 题目大意 \(0\sim m-1\)的数被分成两个集合,你可以分别从两个集合中取一个数相加并对\(m\)取模,求一不能构造出的数. 题解 感觉如果\(\col ...

  6. luoguP4008 [NOI2003]文本编辑器

    题意 splay维护即可 code: #include<bits/stdc++.h> using namespace std; const int maxn=2000010; int T, ...

  7. mongo db 去除 _class 字段

    import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.NoSuc ...

  8. hadoop 输入路径用正则表达式被默认处理为多个参数的问题

    运行命令 hadoop jar   wordcount.jar   com.WordCount  /inpath/*{beijing,shanghai,guangzhou}*   /outpath/ ...

  9. 【LG1600】[NOIP2016]天天爱跑步

    [LG1600][NOIP2016]天天爱跑步 题面 洛谷 题解 考虑一条路径\(S\rightarrow T\)是如何给一个观测点\(x\)造成贡献的, 一种是从\(x\)的子树内出来,另外一种是从 ...

  10. Vue插槽详解 | 什么是插槽?

    作者 | Jeskson 来源 | 达达前端小酒馆 什么是插槽?插槽的指令为v-slot,它目前取代了slot和slot-scope,插槽内容,vue实例一套内容分发的api,将slot元素作为承载分 ...