今天和同事聊到了缓存,在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. Maven国内源设置阿里云地址

    Maven国内源设置 目前国外的maven源访问非常慢,作为一个Java开发者,是一件很痛苦的事,而国内的maven源,oschina已经关闭,目前最好的方式,就是使用阿里云的镜像: <mirr ...

  2. 修复win10无法双击打开txt文档.reg

    Windows Registry Editor Version 5.00[HKEY_CLASSES_ROOT\.txt]@="txtfile""Content Type& ...

  3. 将M个客服随机分配给N个客户

    class AllocUser { //客户多于客服 public static void Test() { var customers = new List<Customer>() { ...

  4. Macbook使用Gitlab配置SSH Key

    git是分布式代码管理工具,远程代码管理是基于ssh的,代码上传大搜gitlab或者github代码仓储时,需要进行ssh配置. 把本地代码上传到服务器时需要加密处理,git中公钥(id_rsa.pu ...

  5. PIE SDK彩色空间变换

    1. 算法功能简介 使用彩色空间变换工具可以将三波段红.绿.蓝图像变换到一个特定的彩色空间,并且能从所选彩色空间变换回 RGB.两次变换之间,通过对比度拉伸,可以生成一个色彩增强的彩色合成图像.此外, ...

  6. 解决 TwebBrowser 不能隐藏的问题

    TOleControl(WebBrowser1).Visible := False

  7. 第四次 Scrum Meeting

    第四次 Scrum Meeting 写在前面 会议时间 会议时长 会议地点 2019/4/8 22:00 30min 大运村1号楼3F 附Github仓库:WEDO 例会照片 工作情况总结(4.8) ...

  8. ElasticSearch:集群(Cluster),节点(Node),分片(Shard),Indices(索引),replicas(备份)之间关系

    [Cluster]集群,一个ES集群由一个或多个节点(Node)组成,每个集群都有一个cluster name作为标识----------------------------------------- ...

  9. centOS7关闭防火墙的命令

    centOS7下关闭防火墙的命令已经改了,如下:      systemctl stop firewalld

  10. Android模拟器访问本机服务器

    Android模拟器访问本机服务器,用127.0.0.1访问不到,因为127.0.0.1已经被映射到模拟器了. 可以用以下两种方式访问 1. 用 10.0.2.2 2. 直接用 本机的IP地址,如:1 ...