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 ...
随机推荐
- 【python】10分钟教你用python一行代码搞点大新闻
准备 相信各位对python的语言简洁已经深有领会了.那么,今天就带大家一探究竟.看看一行python代码究竟能干些什么大新闻.赶紧抄起手中的家伙,跟我来试试吧. 首先你得先在命令行进入python. ...
- Python开发MapReduce系列(一)WordCount Demo
原创,转发请注明出处. MapReduce是hadoop这只大象的核心,Hadoop 中,数据处理核心就是 MapReduce 程序设计模型.一个Map/Reduce 作业(job) 通常会把输入的数 ...
- 微信小程序获取用户手机号,服务器解码demo
原理:通过微信登陆接口wx.login得到encryptedData . iv .code.经过接口处理code得到sessionkey.最后官方demo得到解密后的手机号.(接口处理这一步也可以在 ...
- Spring学习笔记(四)—— Spring中的AOP
一.AOP概述 AOP(Aspect Oriented Programming),即面向切面编程,可以说是OOP(Object Oriented Programming,面向对象编程)的补充和完善.O ...
- Android 使用URL访问网络资源
1.介绍 2.使用方法 3.java后台代码 package com.lucky.test51url; import android.annotation.SuppressLint; import a ...
- LCT小小结
模板题P3690 基础题P3203[HNOI2010]弹飞绵羊 \(access\)是搞出一条端点为\(x,y\)的路径 , 且维护的是实子树的信息 . 由于题目比较简单 , \(access\)时还 ...
- Intelligent Poetry
Readme: Creat poems. import re import random from collections import Counter def Creat_Poem(number): ...
- POJ - 1961 最小循环节
如果循环节存在那在前缀部分也肯定存在 如果循环节存在那至少是可以匹配的 而next是维护最大前缀的,意会意会 注意一定要先判整除,即使别的题目保证是存在循环的 特意画了一张灵魂草图帮助理解 #incl ...
- Spring 配置 Apache Commons Logging
第一次用spring framework,刚配了个最简单的项目,启动出现如下错误,查了知道原来spring要依赖Apache common logging包.只需要添加到项目library中即可.可从 ...
- 关于抓取js加载出来的内容抓取
一.抓取页面 url=https://www.xuexi.cn/f997e76a890b0e5a053c57b19f468436/018d244441062d8916dd472a4c6a0a0b.ht ...