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. python 一些程序规范(跨目录调用文件)

    文档内容学习于 http://www.cnblogs.com/xiaozhiqi/ 参考: https://www.cnblogs.com/monologuesmw/p/9490093.html 软件 ...

  2. springcloud注解解释

    @SpringBootApplication是springboot启动类,包括三个注解,他们的作用分别是:  @Configuration:表示将该类作用springboot配置文件类  @Enabl ...

  3. LiunxCentos7 上安装 FastDFS

    Centos7 上安装 FastDFS 1.安装gcc(编译时需要) FastDFS是C语言开发,安装FastDFS需要先将官网下载的源码进行编译,编译依赖gcc环境,如果没有gcc环境,需要安装gc ...

  4. 以opencv320和vs2013为例说明 vs路径配置方法

    =========================================== 新方法 ======================= 新方法的配置过程,路径之类的设置都是一样. 区别在于,在 ...

  5. USACO Buying Hay

    洛谷 P2918 [USACO08NOV]买干草Buying Hay https://www.luogu.org/problem/P2918 JDOJ 2592: USACO 2008 Nov Sil ...

  6. nowcoder911L 最优子区间

    题目链接 思路 用\(f(i,j)\)表示前i个元素,以i为右端点,j为左端点时的答案. 用个"区间修改,单点查询"的线段树维护出第二维.在从左往右枚举i的过程中.将\([lst_ ...

  7. vue中子组件的methods中获取到props中的值

    这个官网很清楚,也很简单,父组件中使用v-bind绑定传送,子组件使用props接收即可 例如: 父组件中 <template> <div> <head-top>& ...

  8. 【redis】分布式锁实现,与分布式定时任务

    如果你还不知道redis的基本命令与基本使用方法,请看 [redis]redis基础命令学习集合 写在前面 redis辣么多数据结构,这么多命令,具体一点,都可以应用在什么场景呢?用来解决什么具体的问 ...

  9. Kubernetes 学习(十)Kubernetes 容器持久化存储

    0. 前言 最近在学习张磊老师的 深入剖析Kubernetes 系列课程,最近学到了 Kubernetes 容器持久化存储部分 现对这一部分的相关学习和体会做一下整理,内容参考 深入剖析Kuberne ...

  10. C++ 函数重载和参数的缺省值

    一.函数重载 1.1 重载的起源 自然语言中,一个词可以有许多不同的含义,即该词被重载了.人们可以通过上下文来判断该词到底是哪种含义."词的重载"可以使语言更加简练.例如" ...