多级缓存实现类,时间有限,该类未抽取接口,目前只支持两级缓存: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. LengthFieldBasedFrameDecoder

    LengthFieldBasedFrameDecoder 详解 疯狂创客圈 Java 分布式聊天室[ 亿级流量]实战系列之 -31[ 博客园 总入口 ] 文章目录 LengthFieldBasedFr ...

  2. Python 编码错误解决方案

    Python 编码错误解决方案 Python UnicodeDecodeError: 'ascii' codec can't decode byte 0xe5 in position 7: ordin ...

  3. JDK1.8 LocalDate 使用方式;LocalDate 封装Util,LocalDate工具类(四)

    未完待续 ........ 前言:       加班了好几天,终于结束上一个坑的项目了,项目交接人员全部离职,代码一行注释没有,无人问津的情况下,完成了项目,所以好的规范真的很重要. 继续日期改写 一 ...

  4. linux命令:set 指定行,直接替换并修改文件

    sed 命令: 指定行,从第一行到第一行: 把该行的ssd,换成cd: -i 表示的是替换并直接修改文件: sed  -i  '1,1s/ssd/cd/g' test_file 命令使用: sed - ...

  5. amp加载速度比标准移动页面快85%

    6月13日,谷歌合作伙伴大会上Oliver Vidinovski先生(Google Global Head of eCommerce - CS/GCS) 释放了一个信息:amp加载速度比标准移动页面快 ...

  6. 用 tomcat 部署 Jenkins

    在tomcat 下面部署 Jenkins 版本 tomcat (7.0.94) +  jdk (7) + jenkins (2.46.3) 前两次没有部署成功,应该是 jdk 版本的问题, 如果不成功 ...

  7. NOIP 2008 立体图

    洛谷 P1058 立体图 洛谷传送门 JDOJ 1541: [NOIP2008]立体图 T4 JDOJ传送门 题目描述 小渊是个聪明的孩子,他经常会给周围的小朋友们将写自己认为有趣的内容.最近,他准备 ...

  8. dfs的两种处理方法

    方法一: 对于源点s,初始化vis[s]=1,并且在dfs之后vis[s]=1,为下一次调用做准备 .对于dfs递归中的寻找后继的循环体,入栈出栈语句写在循环内. 模板: //调用 vis[s]=; ...

  9. 箭头函数可不用return直接将表达式作为函数返回值

    箭头函数如果函数体只有一个表达式,那么表达式将作为函数的返回值,这种写法无须加上return关键字, 看下面两个函数定义 var testAf = () => '111'; var testAf ...

  10. iptables 表和链的对应关系

    filter表 主要用于对数据包进行过滤,根据具体的规则决定是否放行该数据包(如DROP.ACCEPT.REJECT.LOG).filter 表对应的内核模块为iptable_filter,包含三个规 ...