专注于 JetBrains IDEA 全家桶,永久激活,教程
持续更新 PyCharm,IDEA,WebStorm,PhpStorm,DataGrip,RubyMine,CLion,AppCode 永久激活教程

Java创建本地缓存模拟redis缓存操作

java创建本地缓存,模拟redis的使用

在一般的小项目中,数据量不大.但是有的时候需要使用缓存记录一些标识或者票据之类的,比如我这边想实现,可以记录系统同时在线的用户数据,或者对其他数据的缓存记录,减少DBA请求

1. 创建缓存实体类

package com.adingxiong.cft.entity;

import java.io.Serializable;

/** * @author xiongc * @date 2020/07/28 */ public class CacheEntity implements Serializable { private static final long serialVersionUID = -107853226360392750L; /** * 值 */ private Object value; /** * 保存的时间戳 */ private long gmtModify; /** * 过期时间 */ private int expire; public Object getValue() { return value; } public void setValue(Object value) { this.value = value; } public long getGmtModify() { return gmtModify; } public void setGmtModify(long gmtModify) { this.gmtModify = gmtModify; } public int getExpire() { return expire; } public void setExpire(int expire) { this.expire = expire; } public CacheEntity(Object value, long gmtModify, int expire) { super(); this.value = value; this.gmtModify = gmtModify; this.expire = expire; } } 

2. 创建本地缓存工具类

package com.adingxiong.cft.cache;

import com.adingxiong.cft.entity.CacheEntity;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.CollectionUtils; import java.io.*; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.TimeUnit; /** * @ClassName LocalCache * @Description 本地缓存 代替redis 实现简单数据记录 * @Author xiongchao * @Date 2020/7/28 16:14 **/ public class LocalCache { private static final Logger log = LoggerFactory.getLogger(LocalCache.class); /** * 默认的缓存容量 */ private static final int DEFAULT_CAPACITY = 512; /** * 最大容量 */ private static final int MAX_CAPACITY = 100000; /** * 刷新缓存的频率 */ private static final int MONITOR_DURATION = 2; // 启动监控线程 static { new Thread(new TimeoutTimerThread()).start(); } // 内部类方式实现单例 private static class LocalCacheInstance{ private static final LocalCache INSTANCE=new LocalCache(); } public static LocalCache getInstance() { return LocalCacheInstance.INSTANCE; } private LocalCache() { } /** * 使用默认容量创建一个Map */ private static Map<String, CacheEntity> cache = new ConcurrentHashMap<>(DEFAULT_CAPACITY); /** * 将key-value 保存到本地缓存并制定该缓存的过期时间 * * @param key * @param value * @param expireTime 过期时间,如果是-1 则表示永不过期 * @return */ public <T> boolean putValue(String key, T value, int expireTime) { return putCloneValue(key, value, expireTime); } /** * 将值通过序列化clone 处理后保存到缓存中,可以解决值引用的问题 * * @param key * @param value * @param expireTime * @return */ private <T> boolean putCloneValue(String key, T value, int expireTime) { try { if (cache.size() >= MAX_CAPACITY) { return false; } // 序列化赋值 CacheEntity entityClone = clone(new CacheEntity(value, System.nanoTime(), expireTime)); cache.put(key, entityClone); return true; } catch (Exception e) { log.error("添加缓存失败:{}", e.getMessage()); } return false; } /** * 序列化 克隆处理 * * @param object * @return */ private <E extends Serializable> E clone(E object) { E cloneObject = null; try { ByteArrayOutputStream baos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(baos); oos.writeObject(object); oos.close(); ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); ObjectInputStream ois = new ObjectInputStream(bais); cloneObject = (E) ois.readObject(); ois.close(); } catch (Exception e) { log.error("缓存序列化失败:{}", e.getMessage()); } return cloneObject; } /** * 从本地缓存中获取key对应的值,如果该值不存则则返回null * * @param key * @return */ public Object getValue(String key) { if(CollectionUtils.isEmpty(cache)){ return null; } return cache.get(key).getValue(); } /** * 清空所有 */ public void clear() { cache.clear(); } /** * 过期处理线程 */ static class TimeoutTimerThread implements Runnable { @Override public void run() { while (true) { try { TimeUnit.SECONDS.sleep(MONITOR_DURATION); checkTime(); } catch (Exception e) { log.error("过期缓存清理失败:{}", e.getMessage()); } } } /** * 过期缓存的具体处理方法 * * @throws Exception */ private void checkTime() throws Exception { // 开始处理过期 for (String key : cache.keySet()) { CacheEntity tce = cache.get(key); long timoutTime = TimeUnit.NANOSECONDS.toSeconds(System.nanoTime() - tce.getGmtModify()); // 过期时间 : timoutTime if (tce.getExpire() > timoutTime) { continue; } log.info(" 清除过期缓存 : " + key); //清除过期缓存和删除对应的缓存队列 cache.remove(key); } } } } 

3. 测试

写一个简单的controller

@GetMapping("/cache")
    public Object testCache(String name){
        Object a = LocalCache.getInstance().getValue("name");
        if(a == null){
            LocalCache.getInstance().putValue("name" ,"张三",10);
 return "未读取到缓存数据"; } return "读取到缓存数据,数据为:" + a; } 

第一次调用

46_1.png image

第二次调用 46_2.png

同时服务那边会根据你设定的过期时间去定期启动线程清理缓存数据

46_3.png image

本文使用 tech.souyunku.com 排版

文章永久链接:https://tech.souyunku.com/40802

未经允许不得转载:搜云库技术团队 » Java创建本地缓存模拟redis缓存操作

JetBrains 全家桶,激活、破解、教程

提供 JetBrains 全家桶激活码、注册码、破解补丁下载及详细激活教程,支持 IntelliJ IDEA、PyCharm、WebStorm 等工具的永久激活。无论是破解教程,还是最新激活码,均可免费获得,帮助开发者解决常见激活问题,确保轻松破解并快速使用 JetBrains 软件。获取免费的破解补丁和激活码,快速解决激活难题,全面覆盖 2024/2025 版本!

联系我们联系我们