Java进程内缓存
今天和同事聊到了缓存,在Java中实现进程缓存。这里主要思想是,用一个map做缓存。缓存有个生存时间,过期就删除缓存。这里可以考虑两种删除策略,一种是起一个线程,定期删除过期的key。第二个是,剔除模式,比较懒,访问到某个key的时候才,才去检查这个key是否过期,过期删除。
首先,对要缓存的value做了层封装,带了个时间戳
/**
* Created by gxf on 2017/6/28.
*/
public class ValueWithTimeStamp<V>{
private long expireTime;
private V value; public ValueWithTimeStamp(long expireTime, V value) {
this.expireTime = expireTime;
this.value = value;
} public long getExpireTime() {
return expireTime;
} public void setExpireTime(long expireTime) {
this.expireTime = expireTime;
} public V getValue() {
return value;
} public void setValue(V value) {
this.value = value;
}
}
ok,起线程定期删除策略的模式
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap; /**
* Created by gxf on 2017/6/28.
* 使用线程,定期删除过期的key
*/
public class CacheMap<K, V> {
//这里使用ConcurrentHashMap避免,clean的时候,主线程修改chache,造成异常,
//使用ConcurrentHashMap可以控制并发修改cache
private Map<K, ValueWithTimeStamp<V>> cache = new ConcurrentHashMap<K, ValueWithTimeStamp<V>>();
private static boolean cleanTaskIsRunning = false; //ttl 过期时间 单位:秒
public void put(K key, V value, int ttl){
long expireTime = System.currentTimeMillis() + ttl * 1000;
ValueWithTimeStamp<V> valueWithTimeStamp = new ValueWithTimeStamp<>(expireTime, value);
cache.put(key, valueWithTimeStamp);
if(!cleanTaskIsRunning){
startCleanTask();
cleanTaskIsRunning = !cleanTaskIsRunning;
}
} public V get(K key){
ValueWithTimeStamp<V> valueWithTimeStamp = cache.get(key);
return null == valueWithTimeStamp ? null : valueWithTimeStamp.getValue();
} /**
* 启动清理线程
* */
private void startCleanTask(){
Thread cleanThread = new Thread(new CleanTask());
cleanThread.start();
} /**
* 清理过期的key
* */
class CleanTask implements Runnable{
public void run(){
while(true){
long currentTime = System.currentTimeMillis();
//遍历map
for(Map.Entry<K, ValueWithTimeStamp<V>> entry : cache.entrySet()){
ValueWithTimeStamp<V> valueWithTimeStamp = entry.getValue();
long expireTime = valueWithTimeStamp.getExpireTime();
//过期时间到了
if(currentTime > expireTime){
System.out.println("key : " + entry.getKey() + " expired ");
cache.remove(entry.getKey());
} //if
} //for
//每隔1s扫描map对象
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
} //while
}
}
}
注意,这里需要使用ConcurrentHashMap做缓存。不然会出现多线线程操作map对象的异常
第二种策略,剔除模式
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap; /**
* Created by 58 on 2017/6/28.
* 这里使用懒惰模式,获取key的时候,才剔除过期的key
*/
public class CacheMap1<K, V> {
private Map<K, ValueWithTimeStamp<V>> cache = new ConcurrentHashMap<K, ValueWithTimeStamp<V>>(); public void put(K key, V value, int ttl){
long expireTime = System.currentTimeMillis() + ttl * 1000;
ValueWithTimeStamp<V> valueWithTimeStamp = new ValueWithTimeStamp<V>(expireTime, value);
cache.put(key, valueWithTimeStamp);
} public V get(K key){
ValueWithTimeStamp<V> valueWithTimeStamp = cache.get(key);
long expireTime = valueWithTimeStamp.getExpireTime();
long currentTime = System.currentTimeMillis();
//key已经过期,删除,返回null
if(currentTime > expireTime){
System.out.println("key :" + key + " is expired.");
cache.remove(key);
return null;
} return cache.get(key).getValue();
}
}
项目中用到了redis,用这种方式应该会更快,这两天优化一下代码
Java进程内缓存的更多相关文章
- Java的进程内缓存框架:EhCache (转)
EhCache 是一个纯Java的进程内缓存框架,具有快速.精干等特点,是Hibernate中默认的CacheProvider. Ehcache缓存的特点: 1. 快速. 2. 简单. 3. 多种缓存 ...
- Java的进程内缓存框架:EhCache
EhCache 是一个纯Java的进程内缓存框架,具有快速.精干等特点,是Hibernate中默认的CacheProvider. Ehcache缓存的特点: 1. 快速. 2. 简单. 3. 多种 ...
- 一文深入了解史上最强的Java堆内缓存框架Caffeine
它提供了一个近乎最佳的命中率.从性能上秒杀其他一堆进程内缓存框架,Spring5更是为了它放弃了使用多年的GuavaCache 缓存,在我们的日常开发中用的非常多,是我们应对各种性能问题支持高并发的一 ...
- spring boot:使用spring cache+caffeine做进程内缓存(本地缓存)(spring boot 2.3.1)
一,为什么要使用caffeine做本地缓存? 1,spring boot默认集成的进程内缓存在1.x时代是guava cache 在2.x时代更新成了caffeine, 功能上差别不大,但后者在性能上 ...
- Spring Boot 2.x基础教程:进程内缓存的使用与Cache注解详解
随着时间的积累,应用的使用用户不断增加,数据规模也越来越大,往往数据库查询操作会成为影响用户使用体验的瓶颈,此时使用缓存往往是解决这一问题非常好的手段之一.Spring 3开始提供了强大的基于注解的缓 ...
- java 整合redis缓存 SSM 后台框架 rest接口 shiro druid maven bootstrap html5
A 调用摄像头拍照,自定义裁剪编辑头像,头像图片色度调节B 集成代码生成器 [正反双向](单表.主表.明细表.树形表,快速开发利器)+快速表单构建器 freemaker模版技术 ,0个代码不用写,生成 ...
- java应用本地缓存
在java应用中,对于访问频率比较高,又不怎么变化的数据,常用的解决方案是把这些数据加入缓存.相比DB,缓存的读取效率快好不少.java应用缓存一般分两种,一是进程内缓存,就是使用ja ...
- java问题排查工具之一板斧jstack——使用 jstack 定位 java进程CPU过高的问题
jstack主要用来查看某个Java进程内的线程堆栈信息.语法格式如下: jstack [option] pid jstack [option] executable core jstack [opt ...
- JVM探秘:VisualVM监控远程Java进程
VisualVM在Java 8中是JDK自带的一个图形化工具,项目主页 VisualVM,在后续版本中可能会从JDK移除. VisualVM可以监控Java进程的CPU与内存占用情况,可以监控Java ...
随机推荐
- 在win7系统上搭建django+oracle 11g时,注意事项
在win7系统上搭建django+oracle 11g时,注意事项[示例用的是python 2.7]: 重要:python.oracle.oracle client这三个的OS bit 一定一定要相同 ...
- hdp 2.06 安装备忘
1,官方安装说明文档 http://docs.hortonworks.com/HDPDocuments/HDP2/HDP-2.0.6.0-Win/bk_installing_hdp_for_windo ...
- \\.\Global\vmx86: 系统找不到指定的文件
使用vmware虚拟机时出现如下的错误: vmware安装无法打开内核设备 \\.\Global\vmx86: 系统找不到指定的文件 解决办法: 新建文件,将下面的代码拷贝进去: @Echo Off ...
- 洛谷 P1579 哥德巴赫猜想(升级版)
嗯... 这或许也算一道数论题吧... 题目链接:https://www.luogu.org/problemnew/show/P1579 这道题的说明好像只会扰乱人的思路....然后就是这道题的细节比 ...
- 文件管理NSFileManager
//NSFileManager - (void)viewDidLoad { [super viewDidLoad]; NSLog(@"%@",NSHomeDirectory()); ...
- C++_标准模板库STL概念介绍2-泛型编程
有了之前使用STL的经验后,接下来讨论泛型编程及其底层的理念: 首先我们知道STL只是泛型编程的一种: 而面向对象的编程方式关注的是编程的数据方面: 而泛型编程关注的是算法: 但是,他们之间的一个重要 ...
- visual studio 使用Resharper进行测试
安装Resharper 添加nunit.framework 测试代码 [TestFixture] public class AddresLabelPrintImplTest { [Test] publ ...
- new Date("2018-01-01 11:11:11").valueOf() 在IE下会返回 NaN
原因是在ie下 new Date不能处理 小横线 这种时间格式,但是 替换成 斜线就可以正常获得毫秒数,像下面这样: new Date(('2018-01-01 11:11:11').replace( ...
- table加载慢
为了让大表格(table)在下载的时候可以分段的显示,就是说在浏览器解析html时,table是作为一个整体解释的,使用tbody可以优化显示,如果表格很长,用tbody分段,可以一部分一部分地显示, ...
- [转] docker基础知识之挂载本地目录
[From] https://blog.csdn.net/huludan/article/details/52641090 https://my.oschina.net/piorcn/blog/324 ...