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

package com.ws.commons.cache;

import java.util.function.Supplier;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import com.ws.commons.tool.ThreadTool; /**
* 多级缓存实现
*
* @author 尘无尘
*
*/
public class MultilevelCache {
private static final Logger LOGGER = LoggerFactory.getLogger(MultilevelCache.class); private MultilevelCache() {
} private static final ICache FIRST_LEVE_LCACHE = LocalCache.instance();
private static ICache secondCache; private static final String LOCK_PREFIX = "MUILCACHE_LOCK:"; public static synchronized void init(ICache secondCache) {
if (MultilevelCache.secondCache == null) {
MultilevelCache.secondCache = secondCache;
LOGGER.info("开启二级缓存,secondCache:{}", secondCache);
}
} public static void put(String key, Object value, int timeOutSecond) {
if (secondCache != null) {
secondCache.put(key, value, timeOutSecond);
FIRST_LEVE_LCACHE.put(key, value, cmpFirstCacheTimeOutSecond(timeOutSecond));
} else {
FIRST_LEVE_LCACHE.put(key, value, timeOutSecond);
}
} /**
* 提供数据,并缓存
*
* @param key
* @param supplier
* @return
*/
public static <T> T computeIfAbsent(String key, Supplier<T> supplier) {
T data = FIRST_LEVE_LCACHE.get(key);
if (data == null && secondCache != null) {
data = secondCache.get(key);
}
if (data != null) {
return data;
} synchronized (ThreadTool.buildLock(LOCK_PREFIX, key)) {
data = FIRST_LEVE_LCACHE.get(key);
if (data == null && secondCache != null) {
data = secondCache.get(key);
}
if (data != null) {
return data;
} data = supplier.get();
if (secondCache != null) {
secondCache.put(key, data);
FIRST_LEVE_LCACHE.put(key, data, 60);
} else {
FIRST_LEVE_LCACHE.put(key, data);
}
}
return data;
} /**
* 提供数据,并缓存一定的时间
*
* @param key
* @param timeOutSecond
* @param supplier
* @return
*/
public static <T> T computeIfAbsent(String key, int timeOutSecond, Supplier<T> supplier) {
T data = FIRST_LEVE_LCACHE.get(key);
if (data == null && secondCache != null) {
data = secondCache.get(key);
}
if (data != null) {
return data;
}
synchronized (ThreadTool.buildLock(LOCK_PREFIX, key)) {
data = FIRST_LEVE_LCACHE.get(key);
if (data == null && secondCache != null) {
data = secondCache.get(key);
}
if (data != null) {
return data;
}
data = supplier.get();
if (secondCache != null) {
secondCache.put(key, data, timeOutSecond);
FIRST_LEVE_LCACHE.put(key, data, cmpFirstCacheTimeOutSecond(timeOutSecond));
} else {
FIRST_LEVE_LCACHE.put(key, data, timeOutSecond);
} }
return data;
} public static <T> T removeAndGet(String key) {
T data = null;
if (secondCache != null) {
data = secondCache.removeAndGet(key);
}
T data2 = FIRST_LEVE_LCACHE.removeAndGet(key);
if (data == null) {
data = data2;
}
return data;
} public static void remove(String key) {
if (secondCache != null) {
secondCache.remove(key);
}
FIRST_LEVE_LCACHE.remove(key);
} public static <T> T get(String key) {
T data = FIRST_LEVE_LCACHE.get(key);
if (data == null && secondCache != null) {
data = secondCache.get(key);
}
return data;
} public static void expire(String key, int timeOutSecond) {
FIRST_LEVE_LCACHE.expire(key, timeOutSecond);
if (secondCache != null) {
secondCache.expire(key, timeOutSecond);
}
} private static int cmpFirstCacheTimeOutSecond(int timeOutSecond) {
if (timeOutSecond > 60) {
return 60;
} else if (timeOutSecond > 30) {
return timeOutSecond / 2;
}
return timeOutSecond;
}
}

java手写多级缓存的更多相关文章

  1. java 手写 jvm高性能缓存

    java 手写 jvm高性能缓存,键值对存储,队列存储,存储超时设置 缓存接口 package com.ws.commons.cache; import java.util.function.Func ...

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

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

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

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

  4. 利用Java手写简单的httpserver

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

  5. HashMap+双向链表手写LRU缓存算法/页面置换算法

    import java.util.Hashtable; class DLinkedList { String key; //键 int value; //值 DLinkedList pre; //双向 ...

  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. IDEA中常用的一些设置

    一.idea常用设置1.报错级别    idea默认不会像eclipse一样需要ctrl+s进行保存,并且在保存时会进行编译(可以在File>Settings>Build,Executio ...

  2. 实验十四 团队项目评审&课程学习总结

    项目 内容 这个作业属于哪个课程 2016计算机科学与工程学院软件工程(西北师范大学) 这个作业的要求在哪里 实验十四 团队项目评审&课程学习总结 团队名称 快活帮 作业学习目标 (1)掌握软 ...

  3. 《浅谈我眼中的express、koa和koa2》好文留存+笔记

    原文 :三英战豪强,思绪走四方.浅谈我眼中的express.koa和koa2 一.回调大坑怎么解决呢? 1.es5可以利用一下第三方库,例如 async 库, 2.或者单纯使用 connect中间件  ...

  4. go实现tcp 服务器

    我们将使用 TCP 协议和协程范式编写一个简单的客户端-服务器应用,一个(web)服务器应用需要响应众多客户端的并发请求:Go 会为每一个客户端产生一个协程用来处理请求.我们需要使用 net 包中网络 ...

  5. Invalid connection string format, a valid format is: "host:port:sid"

    报错信息: Caused by: java.sql.SQLException: Io 异常: Invalid connection string format, a valid format is:  ...

  6. ESA2GJK1DH1K升级篇: STM32远程乒乓升级,基于WIFI模块AT指令TCP透传方式,定时访问升级(含有数据校验)

    实现功能概要 定时使用http访问云端的程序版本,如果版本不一致,然后通过http下载最新的升级文件,实现升级. 测试准备工作(默认访问我的服务器,改为自己的服务器,请看后面说明) 一,下载BootL ...

  7. jedis代码操作

    一.jedis快速入门 * Jedis: 一款java操作redis数据库的工具. * 使用步骤: 1. 下载jedis的jar包 2. 使用 //1. 获取连接 Jedis jedis = new ...

  8. web前端图片模糊到清晰的实现过程

    在网页图片显示的时候,会发现许多网站采用了先模糊,然后在慢慢清晰的过程,这样的加载用户体验是比较好的,那么如何实现? 默认加载2张图片,一张缩略图,一张原图,当打开网页的时候默认只显示缩略图,然后我们 ...

  9. 2019年上海市大学生网络安全大赛两道misc WriteUp

    2019年全国大学生网络安全邀请赛暨第五届上海市大学生网络安全大赛 做出了两道Misc== 签到 题干 解题过程 题干提示一直注册成功,如果注册失败也许会出现flag. 下载下来是包含010edito ...

  10. SourceTree安装

    SourceTree安装教程 作为程序员,不可避免的要在github上查询代码,而在企业项目中,为了使得项目好管理需要使用项目管理客户端,所以接下来详细讲解一下基于git的sourceTree在win ...