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

    (1)下载并安装 Eralng 如:otp_win64_20.2.exe (以管理员身份运行安装) (2)下载并安装rabbitmq 如:rabbitmq-server-3.7.4.exe.双击安装, ...

  2. 【mybatis】清空数据库表数据

    <update id="truncateTable"> truncate table ${tableName} </update> <update i ...

  3. idea启动java项目,使用调试会占用更多内存

    idea启动java项目,使用调试会占用更多内存

  4. 【斜率优化】【P5468】 [NOI2019]回家路线

    Description 给定 \(n\) 点,这 \(n\) 个点由 \(m\) 班列车穿插连结.对于第 \(i\) 班列车,会在 \(p_i\) 时刻从 \(x_i\) 站点出发开向 \(y_i\) ...

  5. Biorhythms(信息学奥赛一本通 1639)

    题目描述: 人生来就有三个生理周期,分别为体力.感情和智力周期,它们的周期长度为23天.28天和33天.每一个周期中有一天是高峰.在高峰这天,人会在相应的方面表现出色.例如,智力周期的高峰,人会思维敏 ...

  6. Eclipse对spring-boot,spring-boot-mybatis的搭建

    1.准备工作 1.1.如果没有sts(spring tool suite)插件,  则需要下载. 1.1.1.eclipse下载的话,一定要注意版本,因为eclipse会直接下载最新版本,如果ts版本 ...

  7. Sql Server怎样设置sa用户登录

    首先,我门打开数据库管理工具,用windows方式登录,windows只能本机登录,这样远程的客户端就登录不了,我们目前就是为了开启sa登录,使远程客户端也能访问数据库,看下图,windows方式登录 ...

  8. Android Studio 之 ROM【2】, LiveData+ViewModel+AsyncTask+Repository

    改造上一节 ROM[1], 1.利用 LiveData<List<Word>> 与 observe 中的 onChanged 配合,删除掉之前的textView更新函数(upd ...

  9. nmap简单使用方法

    1.作用扫描整个网络的主机服务状态和存活优点,快速,准确,效率高2.nmap 选项 Usage: nmap [Scan Type(s)] [Options] {target specification ...

  10. Swagger2.9.2进入API界面报NumberFormatException异常

    [转载请注明]: 原文出处:https://www.cnblogs.com/jstarseven/p/11778377.html     作者:jstarseven    码字挺辛苦的.....   ...