今天和同事聊到了缓存,在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进程内缓存的更多相关文章

  1. Java的进程内缓存框架:EhCache (转)

    EhCache 是一个纯Java的进程内缓存框架,具有快速.精干等特点,是Hibernate中默认的CacheProvider. Ehcache缓存的特点: 1. 快速. 2. 简单. 3. 多种缓存 ...

  2. Java的进程内缓存框架:EhCache

    EhCache 是一个纯Java的进程内缓存框架,具有快速.精干等特点,是Hibernate中默认的CacheProvider.   Ehcache缓存的特点: 1. 快速. 2. 简单. 3. 多种 ...

  3. 一文深入了解史上最强的Java堆内缓存框架Caffeine

    它提供了一个近乎最佳的命中率.从性能上秒杀其他一堆进程内缓存框架,Spring5更是为了它放弃了使用多年的GuavaCache 缓存,在我们的日常开发中用的非常多,是我们应对各种性能问题支持高并发的一 ...

  4. spring boot:使用spring cache+caffeine做进程内缓存(本地缓存)(spring boot 2.3.1)

    一,为什么要使用caffeine做本地缓存? 1,spring boot默认集成的进程内缓存在1.x时代是guava cache 在2.x时代更新成了caffeine, 功能上差别不大,但后者在性能上 ...

  5. Spring Boot 2.x基础教程:进程内缓存的使用与Cache注解详解

    随着时间的积累,应用的使用用户不断增加,数据规模也越来越大,往往数据库查询操作会成为影响用户使用体验的瓶颈,此时使用缓存往往是解决这一问题非常好的手段之一.Spring 3开始提供了强大的基于注解的缓 ...

  6. java 整合redis缓存 SSM 后台框架 rest接口 shiro druid maven bootstrap html5

    A 调用摄像头拍照,自定义裁剪编辑头像,头像图片色度调节B 集成代码生成器 [正反双向](单表.主表.明细表.树形表,快速开发利器)+快速表单构建器 freemaker模版技术 ,0个代码不用写,生成 ...

  7. java应用本地缓存

            在java应用中,对于访问频率比较高,又不怎么变化的数据,常用的解决方案是把这些数据加入缓存.相比DB,缓存的读取效率快好不少.java应用缓存一般分两种,一是进程内缓存,就是使用ja ...

  8. java问题排查工具之一板斧jstack——使用 jstack 定位 java进程CPU过高的问题

    jstack主要用来查看某个Java进程内的线程堆栈信息.语法格式如下: jstack [option] pid jstack [option] executable core jstack [opt ...

  9. JVM探秘:VisualVM监控远程Java进程

    VisualVM在Java 8中是JDK自带的一个图形化工具,项目主页 VisualVM,在后续版本中可能会从JDK移除. VisualVM可以监控Java进程的CPU与内存占用情况,可以监控Java ...

随机推荐

  1. 【BZOJ 1877】 [SDOI2009]晨跑(费用流)

    题目描述 Elaxia最近迷恋上了空手道,他为自己设定了一套健身计划,比如俯卧撑.仰卧起坐等 等,不过到目前为止,他坚持下来的只有晨跑. 现在给出一张学校附近的地图,这张地图中包含N个十字路口和M条街 ...

  2. Git 合并两个不同的仓库

    目录 第一步. 下载需要合并的分支 第二步. 添加需要合并远程仓库 第三步. 把base远程仓库中数据抓取到本仓库 第四步. checkount切换到base分支上,命名为 asf 第五步. 合并 总 ...

  3. SDUT OJ 数据结构实验之图论十:判断给定图是否存在合法拓扑序列

    数据结构实验之图论十:判断给定图是否存在合法拓扑序列 Time Limit: 1000 ms Memory Limit: 65536 KiB Submit Statistic Discuss Prob ...

  4. 实现bootstrap的dropdown-menu(下拉菜单)点击后不关闭的方法 (转)

    实现bootstrap的dropdown-menu(下拉菜单)点击后不关闭的方法 问题描述,在下拉菜单中,添加其他元素,例如,原文作者所述的<a>和我自己实际用到的<input> ...

  5. MAC office2016 安装及激活(试了一下,靠谱, 非常感谢原作者)

    转载地址:https://blog.csdn.net/jxq0816/article/details/77248462 非常感谢原作者. 一.安装包下载地址 http://officecdn.micr ...

  6. javascrip 中排序的函数怎么理解

    其中s是数组[888,2222,9,4]:我不明白sort函数中参数是如何作用的,function中的a和b又是干什么的? 那个function的作用就是比较两个数的大小用的,然后返回结果的正负作为排 ...

  7. Django 中的中间件

    Django 中的中间件 Django  中间件 中间件介绍 前戏 之前在判断登录的时候使用的是装饰器的功能,通过给视图函数加装饰器来增加判断是否登录的功能.但此方法的缺点是必须给每个需要判断登录的视 ...

  8. git 下载 安装

    1.下载Git,官网地址:https://git-scm.com/,进入官网首页 在右下方的显示器中找到最新的版本下载,点击下载,跳转到下载页面 下载完成 2.安装Git 双击刚刚下载完成的安装文件, ...

  9. bzoj 1189 二分+最大流

    题目传送门 思路: 先预处理出每个人到每扇门的时间,用门作为起点进行bfs处理. 然后二分时间,假设时间为x,将每扇门拆成1到x,x个时间点,表示这扇门有几个时间点是可以出去的.对于一扇门,每个时间点 ...

  10. WPF Hidden和Collapsed

    对于这两种设定,其实已经提示的很清楚了 Visibility="Hidden"不显示元素,但是在布局为元素保留空间 Visibility="Collapsed" ...