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

  2. USACO Slowing down

    洛谷 P2982 [USACO10FEB]慢下来Slowing down 洛谷传送门 JDOJ 2684: USACO 2010 Feb Gold 3.Slowing down JDOJ传送门 Des ...

  3. Anaconda3(5-1)程序编辑器 自带的spyder

    1装好后自带spyder编辑器 2 打开软件 3 每次程序需要制定anaconda3中创建的虚拟环境对应 的python版本的路径 例如在我的电脑我创建了两个环境 而我的pytorch安装在pytho ...

  4. postfix发邮件失败,日志和postqueue -p提示Connection refused

    1. postfix服务未启动 2. /etc/postfix/main.cf文件中未设置inet_interfaces = all

  5. R语言学习(基本知识)

    0)查看帮助 library(help="ballgown") #查看包帮助 getwd() #查看当前工作目录 setwd('C:/Users/djx/Desktop/信号肽系统 ...

  6. P3258 [JLOI2014]松鼠的新家题解

    题目描述 松鼠的新家是一棵树,前几天刚刚装修了新家,新家有\(n\)个房间,并且有\(n-1\)根树枝连接,每个房间都可以相互到达,且俩个房间之间的路线都是唯一的.天哪,他居然真的住在"树& ...

  7. ##C++ format 格式化字符串

    C++ format 格式化字符串实现方式 1. http://stackoverflow.com/questions/2342162/stdstring-formatting-like-sprint ...

  8. Android 从零编写一个带标签 TagTextView

    最近公司的项目升级到了 9.x,随之而来的就是一大波的更新,其中有个比较明显的改变就是很多板块都出了一个带标签的设计图,如下: 怎么实现 看到这个,大多数小伙伴都能想到这就是一个简单的图文混排,不由得 ...

  9. Gamma阶段第七次scrum meeting

    每日任务内容 队员 昨日完成任务 明日要完成的任务 张圆宁 #91 用户体验与优化https://github.com/rRetr0Git/rateMyCourse/issues/91(持续完成) # ...

  10. 【Gamma】Scrum Meeting 7

    前言 会议定点:大运村公寓 会议时间:2019/6/5 会议目的:明确下阶段目标 一.任务进度 组员 上周任务进度 下阶段任务 大娃 修复后端bug 辅助做好引导录屏 二娃 撰写会议博客 撰写会议博客 ...