Java实现一个简单的缓存

article/2025/9/1 18:32:24

cache


阅读原文请访问我的博客BrightLoong's Blog
  缓存是在web开发中经常用到的,将程序经常使用到或调用到的对象存在内存中,或者是耗时较长但又不具有实时性的查询数据放入内存中,在一定程度上可以提高性能和效率。下面我实现了一个简单的缓存,步骤如下。

创建缓存对象EntityCache.java

public class EntityCache {/*** 保存的数据*/private  Object datas;/*** 设置数据失效时间,为0表示永不失效*/private  long timeOut;/*** 最后刷新时间*/private  long lastRefeshTime;public EntityCache(Object datas, long timeOut, long lastRefeshTime) {this.datas = datas;this.timeOut = timeOut;this.lastRefeshTime = lastRefeshTime;}public Object getDatas() {return datas;}public void setDatas(Object datas) {this.datas = datas;}public long getTimeOut() {return timeOut;}public void setTimeOut(long timeOut) {this.timeOut = timeOut;}public long getLastRefeshTime() {return lastRefeshTime;}public void setLastRefeshTime(long lastRefeshTime) {this.lastRefeshTime = lastRefeshTime;}}

定义缓存操作接口,ICacheManager.java

public interface ICacheManager {/*** 存入缓存* @param key* @param cache*/void putCache(String key, EntityCache cache);/*** 存入缓存* @param key* @param cache*/void putCache(String key, Object datas, long timeOut);/*** 获取对应缓存* @param key* @return*/EntityCache getCacheByKey(String key);/*** 获取对应缓存* @param key* @return*/Object getCacheDataByKey(String key);/*** 获取所有缓存* @param key* @return*/Map<String, EntityCache> getCacheAll();/*** 判断是否在缓存中* @param key* @return*/boolean isContains(String key);/*** 清除所有缓存*/void clearAll();/*** 清除对应缓存* @param key*/void clearByKey(String key);/*** 缓存是否超时失效* @param key* @return*/boolean isTimeOut(String key);/*** 获取所有key* @return*/Set<String> getAllKeys();
}

实现接口ICacheManager,CacheManagerImpl.java

  这里我使用了ConcurrentHashMap来保存缓存,本来以为这样就是线程安全的,其实不然,在后面的测试中会发现它并不是线程安全的。

public class CacheManagerImpl implements ICacheManager {private static Map<String, EntityCache> caches = new ConcurrentHashMap<String, EntityCache>();/*** 存入缓存* @param key* @param cache*/public void putCache(String key, EntityCache cache) {caches.put(key, cache);}/*** 存入缓存* @param key* @param cache*/public void putCache(String key, Object datas, long timeOut) {timeOut = timeOut > 0 ? timeOut : 0L;putCache(key, new EntityCache(datas, timeOut, System.currentTimeMillis()));}/*** 获取对应缓存* @param key* @return*/public EntityCache getCacheByKey(String key) {if (this.isContains(key)) {return caches.get(key);}return null;}/*** 获取对应缓存* @param key* @return*/public Object getCacheDataByKey(String key) {if (this.isContains(key)) {return caches.get(key).getDatas();}return null;}/*** 获取所有缓存* @param key* @return*/public Map<String, EntityCache> getCacheAll() {return caches;}/*** 判断是否在缓存中* @param key* @return*/public boolean isContains(String key) {return caches.containsKey(key);}/*** 清除所有缓存*/public void clearAll() {caches.clear();}/*** 清除对应缓存* @param key*/public void clearByKey(String key) {if (this.isContains(key)) {caches.remove(key);}}/*** 缓存是否超时失效* @param key* @return*/public boolean isTimeOut(String key) {if (!caches.containsKey(key)) {return true;}EntityCache cache = caches.get(key);long timeOut = cache.getTimeOut();long lastRefreshTime = cache.getLastRefeshTime();if (timeOut == 0 || System.currentTimeMillis() - lastRefreshTime >= timeOut) {return true;}return false;}/*** 获取所有key* @return*/public Set<String>  getAllKeys() {return caches.keySet();}
}

CacheListener.java,监听失效数据并移除。

public class CacheListener{Logger logger = Logger.getLogger("cacheLog");private CacheManagerImpl cacheManagerImpl;public CacheListener(CacheManagerImpl cacheManagerImpl) {this.cacheManagerImpl = cacheManagerImpl;}public void startListen() {new Thread(){public void run() {while (true) {for(String key : cacheManagerImpl.getAllKeys()) {if (cacheManagerImpl.isTimeOut(key)) {cacheManagerImpl.clearByKey(key);logger.info(key + "缓存被清除");}} }}  }.start();}
}

测试类TestCache.java

public class TestCache {Logger logger = Logger.getLogger("cacheLog");/*** 测试缓存和缓存失效*/@Testpublic void testCacheManager() {CacheManagerImpl cacheManagerImpl = new CacheManagerImpl();cacheManagerImpl.putCache("test", "test", 10 * 1000L);cacheManagerImpl.putCache("myTest", "myTest", 15 * 1000L);CacheListener cacheListener = new CacheListener(cacheManagerImpl);cacheListener.startListen();logger.info("test:" + cacheManagerImpl.getCacheByKey("test").getDatas());logger.info("myTest:" + cacheManagerImpl.getCacheByKey("myTest").getDatas());try {TimeUnit.SECONDS.sleep(20);} catch (InterruptedException e) {e.printStackTrace();}logger.info("test:" + cacheManagerImpl.getCacheByKey("test"));logger.info("myTest:" + cacheManagerImpl.getCacheByKey("myTest"));}/*** 测试线程安全*/@Testpublic void testThredSafe() {final String key = "thread";final CacheManagerImpl cacheManagerImpl = new CacheManagerImpl();ExecutorService exec = Executors.newCachedThreadPool();for (int i = 0; i < 100; i++) {exec.execute(new Runnable() {public void run() {if (!cacheManagerImpl.isContains(key)) {cacheManagerImpl.putCache(key, 1, 0);} else {//因为+1和赋值操作不是原子性的,所以把它用synchronize块包起来synchronized (cacheManagerImpl) {int value = (Integer) cacheManagerImpl.getCacheDataByKey(key) + 1; cacheManagerImpl.putCache(key,value , 0);}}}});}exec.shutdown();  try {exec.awaitTermination(1, TimeUnit.DAYS);} catch (InterruptedException e1) {e1.printStackTrace();}  logger.info(cacheManagerImpl.getCacheDataByKey(key).toString());}
}

testCacheManager()输出结果如下:

2017-4-17 10:33:51 io.github.brightloong.cache.TestCache testCacheManager
信息: test:test
2017-4-17 10:33:51 io.github.brightloong.cache.TestCache testCacheManager
信息: myTest:myTest
2017-4-17 10:34:01 io.github.brightloong.cache.CacheListener$1 run
信息: test缓存被清除
2017-4-17 10:34:06 io.github.brightloong.cache.CacheListener$1 run
信息: myTest缓存被清除
2017-4-17 10:34:11 io.github.brightloong.cache.TestCache testCacheManager
信息: test:null
2017-4-17 10:34:11 io.github.brightloong.cache.TestCache testCacheManager
信息: myTest:null

testThredSafe()输出结果如下(选出了各种结果中的一个举例):

2017-4-17 10:35:36 io.github.brightloong.cache.TestCache testThredSafe
信息: 96

可以看到并不是预期的结果100,为什么呢?ConcurrentHashMap只能保证单次操作的原子性,但是当复合使用的时候,没办法保证复合操作的原子性,以下代码:

if (!cacheManagerImpl.isContains(key)) {cacheManagerImpl.putCache(key, 1, 0);}

多线程的时候回重复更新value,设置为1,所以出现结果不是预期的100。所以办法就是在CacheManagerImpl.java中都加上synchronized,但是这样一来相当于操作都是串行,使用ConcurrentHashMap也没有什么意义,不过只是简单的缓存还是可以的。或者对测试方法中的run里面加上synchronized块也行,都是大同小异。更高效的方法我暂时也想不出来,希望大家能多多指教。


http://chatgpt.dhexx.cn/article/3Z0ob0j9.shtml

相关文章

java中缓存简介

外存&#xff1a; 也就是我们经常说的&#xff08;CDEF盘的大小&#xff09;外储存器是指除计算机内存及CPU缓存以外的储存器&#xff0c;此类储存器一般断电后仍然能保存数据。常见的外存储器有硬盘、软盘、光盘、U盘等&#xff0c;一般的软件都是安装在外存中 内存&#xff1…

java缓存学习

首先说一下缓存著名的开源框架&#xff1a; 最出名的当属 Redis 和 Memcached 了&#xff0c;它们因为使用简便、高性能而成为事实上的标准。还有一些是比较有名的Java开源缓存框架&#xff0c;例如Ehcache、GuavaCache 和 Caffeine 静态缓存和动态缓存&#xff1a; 所谓静态…

JAVA缓存技术

最近再ITEYE上看到关于讨论JAVA缓存技术的帖子比较多,自己不懂,所以上网大概搜了下,找到一篇,暂作保存,后面如果有用到可以参考。此为转贴,帖子来处:http://cogipard.info/articles/cache-static-files-with-jnotify-and-ehcache 介绍 JNotify:http://jnotify.sourcefor…

Java缓存机制

1 Java缓存 1.1 jvm内置缓存 Java中实现缓存的方式有很多&#xff0c;比如用static hashMap基于内存缓存的jvm内置缓存&#xff0c;简单不实用&#xff0c;保对象的有效性和周期无法控制&#xff0c;容易造成内存急剧上升。常用的有Oscache&#xff08;主要针对jsp页面&#…

java中Cache缓存的使用

java中Cache缓存 1.JSR107 缓存的整体架构&#xff1a; 2.SpringBoot的缓存抽象 几个重要概念以及缓存注解 其中想要使用缓存直接&#xff0c;就必须开启**EnableCaching**注解 开启缓存注解的步骤&#xff1a; 作为Spring框架的核心功能之缓存注解&#xff0c;该功能也继承…

JAVA缓存的实现

缓存可分为二大类: 一、通过文件缓存,顾名思义文件缓存是指把数据存储在磁盘上&#xff0c;不管你是以XML格式&#xff0c;序列化文件DAT格式还是其它文件格式&#xff1b; 二、内存缓存&#xff0c;也就是实现一个类中静态Map,对这个Map进行常规的增删查. 下面为一个简单的缓…

java缓存技术的介绍

一、什么是缓存 1、Cache是高速缓冲存储器 一种特殊的存储器子系统&#xff0c;其中复制了频繁使用的数据以利于快速访问 2、凡是位于速度相差较大的两种硬件/软件之间的&#xff0c;用于协调两者数据传输速度差异的结构&#xff0c;均可称之为 Cache 二、缓存的分类 1、基于we…

Java缓存介绍

一、缓存 1、什么是缓存&#xff1f; 缓存是硬件&#xff0c;是CPU中的组件&#xff0c;CPU存取数据的速度非常的快&#xff0c;一秒钟能够存取、处理十亿条指令和数据&#xff08;术语&#xff1a;CPU主频1G&#xff09;&#xff0c;而内存就慢很多&#xff0c;快的内存能够达…

Java实现本地缓存、分布式缓存及多级缓存

以下均为自己参考其它博主文章或自己理解整理而成&#xff0c;如有错误之处&#xff0c;欢迎在评论区批评指正&#xff01; 0. 缓存简介 像MySql等传统的关系型数据库已经不能适用于所有的业务场景&#xff0c;比如电商系统的秒杀场景&#xff0c;APP首页的访问流量高峰场景&a…

Java本地高性能缓存的几种实现方式

Java缓存技术可分为远端缓存和本地缓存&#xff0c;远端缓存常用的方案有著名的redis和memcache&#xff0c;而本地缓存的代表技术主要有HashMap&#xff0c;Guava Cache&#xff0c;Caffeine和Encahche。本篇博文仅覆盖了本地缓存&#xff0c;且突出探讨高性能的本地缓存。 本…

SIFT的两个版本:OpenCV和VL_SIFT

暂时记录一下 OpenCV版本&#xff1a; #include<iostream> #include<opencv2/opencv.hpp> #include<opencv2/core.hpp> #include<opencv2/features2d.hpp> #include <opencv2/xfeatures2d/nonfree.hpp>using namespace std; using namespace c…

论文阅读笔记《Matching Images With Multiple Descriptors: An Unsupervised Approach for Locally Adaptive》

核心思想 本文提出一种将多种特征描述算法融合起来实现更好图像匹配的方法。近些年来&#xff0c;图像特征的描述算法层出不穷如SIFT、LIOP 、DAISY等等&#xff0c;每种方法都有各自的优势和侧重点&#xff0c;对于不同图像其效果也各有优劣。那么能不能将多种算法的优势结合起…

LIFT: Learned Invariant Feature Transform详细笔记

LIFT: Learned Invariant Feature Transform Paper: LIFT: Learned Invariant Feature Transform | SpringerLink Code: GitHub - cvlab-epfl/LIFT: Code release for the ECCV 2016 paper 文章目录 Abstract思路来源LIFT文献来源 方法&#xff1a;LIFTPipeline网络架构训练流…

简单的倒计时shell脚本

效果如下: 代码如下: #! /bin/bash #####################倒计时################ #作者:liop #完成时间:2019.12.17 #三位数以内秒数的倒计时 ########################################## display(){case $1 in1)case $2 in1)echo "******** ";;2)echo "…

计算机视觉领域经典论文源码

计算机视觉领域经典论文源码 转载自&#xff1a;http://blog.csdn.net/ddreaming/article/details/52416643 2016-CVPR论文代码资源&#xff1a; https://tensortalk.com/?catconference-cvpr-2016 一个GitHub账号&#xff0c;里面有很多计算机视觉领域最新论文的代码实现&am…

【译文】Local Intensity Order Pattern for Feature Description

在上一篇文章【特征检测】LIOP特征描述算法中讲到了LIOP描述符&#xff0c;下面我将原文翻译如下&#xff0c;如有出入请以原文为准。 —————————————————————————————————————————————————————————————————…

[2015 Springer] Local Image Descriptor: Modern Approaches——2 Classical Local Descriptors

转载请注明链接&#xff1a; 有问题请及时联系博主&#xff1a;Alliswell_WP 第一篇链接&#xff1a;https://blog.csdn.net/qq_21685903/article/details/103475243 第二篇链接&#xff1a;https://blog.csdn.net/qq_21685903/article/details/103610331 翻译 本地图像描述…

[2015 Springer] Local Image Descriptor: Modern Approaches——3 Intensity Order-Based Local Descriptors

转载请注明链接&#xff1a; 有问题请及时联系博主&#xff1a;Alliswell_WP&#xff1a;Alliswell_WP 第一篇链接&#xff1a;https://blog.csdn.net/qq_21685903/article/details/103475243 第二篇链接&#xff1a;https://blog.csdn.net/qq_21685903/article/details/10361…

在SIFT和SURF之后,有哪些比较新的且具有一定影响力的自然图像配准算法?

链接&#xff1a;https://www.zhihu.com/question/32066833/answer/2041516754 编辑&#xff1a;深度学习与计算机视觉 声明&#xff1a;仅做学术分享&#xff0c;侵删 作者&#xff1a;Vinjn张静https://www.zhihu.com/question/32066833/answer/54575191 我就提一下 OpenCV 中…

matlab vlfeat hog,vlfeat-0.9.20-bin 特征提取的工具包,实现各种 ,如hog,lbp,sift. matlab 242万源代码下载- www.pudn.com...

文件名称: vlfeat-0.9.20-bin下载 收藏√ [ 5 4 3 2 1 ] 开发工具: matlab 文件大小: 17828 KB 上传时间: 2015-07-21 下载次数: 0 提 供 者: 刘晓晶 详细说明&#xff1a;特征提取的工具包&#xff0c;实现各种特征&#xff0c;如hog,lbp,sift.-Feature extraction kit …