用Java写一个简单的缓存操作类

前言

使用缓存已经是开发中老生常谈的一件事了,常用专门处理缓存的工具比如Redis、MemCache等,但是有些时候可能需要一些简单的缓存处理,没必要用上这种专门的缓存工具,那么自己写一个缓存类最合适不过了。

一、分析

首先分析一下缓存类该如何设计,这里我以一种非常简单的方式来实现一个缓存类,这也是我一直以来使用的设计方案。

为了明确功能,首先定义一个接口类CacheInt,然后是缓存实现的工具类CacheUtil。然后再看其中的功能,为了存取方便,缓存应是以键值对的形式存取,为了适应更多的场景,所以在存取的时候可以加一个缓存过期时间,然后再加上其他常见的添加、获取、删除、缓存大小、是否存在key、清理过期缓存等方法,整个缓存工具的方法差不多就是这些。

缓存类需要注意的问题:

  1. 缓存对象应该是唯一的,也就是单例的;
  2. 缓存的操作方法要同步,在多线程并发条件下防止出错;
  3. 缓存的容器应该具有较高的并发性能,ConcurrentHashMap是一个不错的选择。

二、具体实现

1. CacheInt接口的定义

CacheInt接口的定义如下:

2. CacheUtil的具体实现

缓存实现的核心就是CacheUtil,下面结合注释进行说明,为了避免文章篇幅冗杂,以下截图就是完整源码截图,并且保持先后顺序。

首先是类定义和其属性定义,其中本类实例对象用volatile进行修饰提高可见性,初始化缓存容量用于初始化ConcurrentHashMap缓存容器的大小,此大小根据实际应用场景进行优化

然后是内部类Entry的定义,该类是用来存储实际数据的,为了方便处理过期时间,添加初始化时间戳、过期时间等属性。

然后是使用双检锁单例方式获取本类实例对象,因为单例只能存在唯一的特点,所以注意构造函数需要设为private

接下来是存入缓存数据put()方法,这里的clearExpiredCache()是清理过期缓存,后面会看到方法体,因为在我项目中存入缓存的情况较少,所以这里我固定了每次存之前先清理一次过期时间缓存,这里可以根据自己项目实际情况进行优化。

然后是获取缓存get()方法,因为获取数据的时间较为多数,所以这里我设定了三分之一的概率清理过期缓存,适当地释放堆内存,并且在获取时检测是否过期,如果已过期然而还获取到了,就删除并返回空。

然后就是比较常规的一些方法,具体可以看代码

最后一个方法就是清理过期缓存,这里你可以选择启动一个监听线程实时地清理缓存,也可以选择在适当时机进行一次清理,比如我这里就是在存在put和get操作时固定或概率地清理缓存。

三、并发测试

普通的实现测试这里就不展示了,肯定是没问题的,读者简单写一些测试样例即可,这里主要展示一下并发测试,因为在实际情况中存在并发处理缓存情况,为了确保其正确性,所以并发测试是必须要做的,下面放出我的测试样例。

最后测试的表现是很好,没有出现不正确的情况,部分测试结果截图如下:

四、拓展

该类只是简单的实现了缓存的过程,但是在实际应用中不见得能很好地表现,首先它的容量肯定有限,不能存太多缓存,因为使用的是JVM堆内的内存,其次其功能也较为简单,比如不支持LRU淘汰等,这个可以用双链表+Map或者是LinkedHashMap去实现,更多功能都可以拓展。

本文分享自微信公众号 - 北风IT之路(beifengtz)

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2019-07-13

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Jerry的SAP技术分享

Another approach to enable table edit in SE16

例如默认情况下,需要直接在dev system的SE16里修改某些table entry的value,但是 toolbar里看不见edit icon:

9640
来自专栏计算机编程

Okkt —— 一款针对kotlin语言封装的Okhttp网络请求库

1、针对文件请求,重写okio计算方案,可实时显示请求文件进度,防止okhttp在直接做请求文件的时候采取的直传策略,从而导致下载文件间隔过长。

42230
来自专栏Jerry的SAP技术分享

CRM_REPORT_RF_AUTH_OBJ_ORD_LP

9760
来自专栏浩Coding

车辆违章查询和限行提醒程序 -- (3) 接入车辆违章查询接口

接下来我们要接入违章查询接口啦,然后就可以根据查询结果决定是否发送邮件提醒用户。

28330
来自专栏浩Coding

获取访问者IP -- 基于Servlet方式

最近做一个小项目,需要在本地电脑上不断调试数据接口,但是由于用的是路由器上网,所以公网IP是不断变化的,这就很麻烦了,所以写一个小程序,每次返回访问者IP,没有...

9430
来自专栏Jerry的SAP技术分享

CRM_REPORT_RF_AUTH_OBJ_ORD_PR

11140
来自专栏浩Coding

车辆违章查询和限行提醒程序 -- (2) Java实现发送邮件

下面我们介绍如何用Java发送邮件,综合网上资料我制作了一篇肥肠简单的教程,只要把邮箱密码和接收者邮箱账户替换成你需要的即可!!!当然,发送邮件虽然没有成本,但...

17340
来自专栏Jerry的SAP技术分享

Java三维数组的使用

11940
来自专栏清晨我上码

zuul 请求重写

12360
来自专栏Jerry的SAP技术分享

CL_CRM_REPORT_ACCRULE_ONEORDER

7230

扫码关注云+社区

领取腾讯云代金券

年度创作总结 领取年终奖励