栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

站在巨人的肩上,基于Java8手写本地缓存

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

站在巨人的肩上,基于Java8手写本地缓存

站在巨人的肩上,基于Java8手写本地缓存

文章目录
    • 站在巨人的肩上,基于Java8手写本地缓存
        • 0、写在最前面
        • 1、缓存类具备的功能
        • 2、创建缓存类
        • 3、添加键值对方法
        • 4、根据 key 获取相应的value
        • 5、删除键值对
        • 6、处理已经失效的键值对
        • 7、基于java提供的Timer定时执行缓存类的失效监测处理方法
        • 8、CacheUtil 完整代码
        • 9、测试类
        • 10、测试结果如下
        • 11、项目下载地址

0、写在最前面

1、大多数业务场景下 ,为了提高系统的响应速度,使用缓存是最佳的选择;

2、由于本人工作性质特殊纯内网开发,在用maven导依赖无果后一气之下决定自己手写一个 简单的本地缓存来满足自己的业务需求

3、本文仅用于分享学习!!!

1、缓存类具备的功能
  • 存储键值对 put()
  • 存储一定有效期的键值对 put()
  • 获取键值对 get()
  • 删除键值对 remove()
  • 定期清理过期的键值对 handleExpiredKeys()

项目目录结构如下:

2、创建缓存类

创建 CacheUtil.java 详细代码如下:

import java.util.concurrent.ConcurrentHashMap;


public class CacheUtil {
    
    private ConcurrentHashMap cacheMap = null;
    
    private ConcurrentHashMap expireMap = null;
    
    private final long DEFAULT_EXPIRE_TIME = 1000 * 3600 * 24 * 30;

    private static CacheUtil instance = null;


    public static CacheUtil getInstance(){
        if (null == instance){
            synchronized (CacheUtil.class){
                if (null == instance)instance = new CacheUtil();
            }
        }
        return instance;
    }

    CacheUtil(){
        cacheMap = new ConcurrentHashMap<>();
        expireMap = new ConcurrentHashMap<>();
    }
}
3、添加键值对方法

在缓存工具类中实现添加键值对的方法

    
    public void put(String key, Object value){
        this.put(key, value, DEFAULT_EXPIRE_TIME);
    }

    
    public void put(String key, Object value, long expire){
        cacheMap.put(key, value);
        expireMap.put(key, System.currentTimeMillis() + expire);
    }
4、根据 key 获取相应的value
    
    public Object get(String key){
        return cacheMap.get(key);
    }
5、删除键值对

根据提供的键值从map中删除相应的键值 对并返回被删除的键值对个数

    
    public int remove(String key){
        int beforeRemoveCount = cacheMap.size();

        int afterRemoveCount = cacheMap.size();
        return beforeRemoveCount - afterRemoveCount;
    }
6、处理已经失效的键值对

1)、基于过期时间map的过期时间进行排序

2)、遍历排序后的map

3)、判断键值对是否过期,过期则删除键值对

详细代码如下 :

    
    public int handleExpireKeys(){
        long now = System.currentTimeMillis();
        int beforeRemoveCount = cacheMap.size();
        List> collect = expireMap.entrySet().stream()
                .sorted((entry1, entry2) -> entry1.getValue().compareTo(entry2.getValue()))
                .collect(Collectors.toList());
        Iterator> iterator = collect.iterator();
        while (iterator.hasNext()){
            Map.Entry kv = iterator.next();
            String key = kv.getKey();
            Long expireTime = kv.getValue();
            if (expireTime < now){
                this.remove(key);
                System.out.println(String.format("%s过期,已删除", key));
            }
        }
        int afterRemoveCount = cacheMap.size();
        int removeCount = beforeRemoveCount - afterRemoveCount;
        if (removeCount < 0)removeCount = 0;
        System.out.println("当前过期键值对:" + removeCount);
        return removeCount;
    }
7、基于java提供的Timer定时执行缓存类的失效监测处理方法
import java.util.Timer;
import java.util.TimerTask;

public class CacheHandleSchedule {
    public void start(){
        TimerTask timerTask = new TimerTask() {
            @Override
            public void run() {
                CacheUtil.getInstance().handleExpireKeys();
            }
        };
        // 在指定延迟0毫秒后开始,随后地执行以1000毫秒间隔执行timerTask
        new Timer().schedule(timerTask, 0L, 1000L);
    }
}
8、CacheUtil 完整代码
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;


public class CacheUtil {
    
    private ConcurrentHashMap cacheMap = null;
    
    private ConcurrentHashMap expireMap = null;
    
    private final long DEFAULT_EXPIRE_TIME = 1000 * 3600 * 24 * 30;

    private static CacheUtil instance = null;


    public static CacheUtil getInstance(){
        if (null == instance){
            synchronized (CacheUtil.class){
                if (null == instance)instance = new CacheUtil();
            }
        }
        return instance;
    }

    CacheUtil(){
        cacheMap = new ConcurrentHashMap<>();
        expireMap = new ConcurrentHashMap<>();
    }

    
    public void put(String key, Object value){
        this.put(key, value, DEFAULT_EXPIRE_TIME);
    }

    
    public void put(String key, Object value, long expire){
        cacheMap.put(key, value);
        expireMap.put(key, System.currentTimeMillis() + expire);
    }

    
    public Object get(String key){
        return cacheMap.get(key);
    }

    
    public int remove(String key){
        int beforeRemoveCount = cacheMap.size();
        cacheMap.remove(key);
        expireMap.remove(key);
        int afterRemoveCount = cacheMap.size();
        return beforeRemoveCount - afterRemoveCount;
    }

    
    public int handleExpireKeys(){
        long now = System.currentTimeMillis();
        int beforeRemoveCount = cacheMap.size();
        List> collect = expireMap.entrySet().stream()
                .sorted((entry1, entry2) -> entry1.getValue().compareTo(entry2.getValue()))
                .collect(Collectors.toList());
        Iterator> iterator = collect.iterator();
        while (iterator.hasNext()){
            Map.Entry kv = iterator.next();
            String key = kv.getKey();
            Long expireTime = kv.getValue();
            if (expireTime < now){
                this.remove(key);
                System.out.println(String.format("%s过期,已删除", key));
            }
        }
        int afterRemoveCount = cacheMap.size();
        int removeCount = beforeRemoveCount - afterRemoveCount;
        if (removeCount < 0)removeCount = 0;
        System.out.println("当前过期键值对:" + removeCount);
        return removeCount;
    }
}
9、测试类
import com.negen.CacheHandleSchedule;
import com.negen.CacheUtil;

public class TestCacheUtil {
    public static void main(String[] args) {
        CacheHandleSchedule cacheHandleSchedule = new CacheHandleSchedule();
        cacheHandleSchedule.start();
        CacheUtil cacheUtil = CacheUtil.getInstance();
        cacheUtil.put("zhangsan", "zhangsan", 100);
        cacheUtil.put("lisi", "lisi", 1200);
        cacheUtil.put("w5", "w5", 1300);
        Object zhangsan = cacheUtil.get("zhangsan");
        if (null != zhangsan)
            System.out.printf((String)zhangsan);
    }
}
10、测试结果如下

11、项目下载地址

https://download.csdn.net/download/qq_36657751/86264631

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1031593.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号