使用Java实现一个缓存

news/2024/7/8 2:58:30

啥也不说,直接上代码,欢迎指正。

package com.example.demo.cache;

/**
 * @className: JdkCache
 * @description: TODO 类描述
 * @author: Yang.H
 * @date: 2021/8/2014:26
 **/

import lombok.extern.slf4j.Slf4j;

import java.util.Date;
import java.util.Map;
import java.util.concurrent.*;

/**
 * 设计一个JDK缓存
 */
@Slf4j
public class JdkCache {
    private static final long NO_EXPIRE_TIME = -1;
    // Key,Value 容器
    private static final Map<String, ValueHolder> LOCAL_CACHE = new ConcurrentHashMap<>();

    private static class ValueHolder {
        // 缓存值
        private String value;
        // 修改时间
        private Date modifyTime;
        // 过期时间
        private long expireTime;
    }

    private static final ScheduledExecutorService exeService = new ScheduledThreadPoolExecutor(1, (r) -> {
        Thread thread = new Thread(r);
        thread.setDaemon(true);
        thread.setName("JDK失效缓存清空守护线程");
        return thread;
    });

    static {
        // 类初始化时,创建一个线程,用于不断的去判断key是否过期,然后删除。
        exeService.scheduleAtFixedRate(() -> {
            for (Map.Entry<String, ValueHolder> entry : LOCAL_CACHE.entrySet()) {
                if (isExpire(entry.getValue())) {
                    String value = removeKey(entry.getKey());
                    log.info("缓存已失效。键:{}, 缓存值:{}", entry.getKey(), value);
                } else {
                    log.info("缓存未失效。键:{}", entry.getKey());
                }
            }
        }, 0, 500, TimeUnit.MILLISECONDS);
    }


    private static boolean isExpire(ValueHolder holder) {
        if (holder.expireTime <= 0) { //不失效
            return false;
        }
        return new Date().getTime() > holder.modifyTime.getTime() + holder.expireTime;
    }

    /**
     * 删除过期的key,并返回值。返回null表示不符合要求
     *
     * @param key
     * @return
     */
    private static String removeExpireKey(String key) {
        ValueHolder holder = LOCAL_CACHE.get(key);
        if (holder != null && isExpire(holder)) {
            log.info("缓存已失效。键:{}", key);
            return (holder = LOCAL_CACHE.remove(key)) != null ? holder.value : null;
        }
        return null;
    }

    /**
     * 删除key
     *
     * @param key
     * @return
     */
    public static String removeKey(String key) {
        ValueHolder holder;
        return (holder = LOCAL_CACHE.remove(key)) != null ? holder.value : null;
    }


    /**
     * 存储,KV,但是过期时间不刷新
     * @param key
     * @param value
     * @param millSecond
     * @return
     */
    public static String put(String key, String value, long millSecond) {
        removeExpireKey(key);
        ValueHolder valueHolder = LOCAL_CACHE.get(key);
        if (valueHolder != null){
            valueHolder.value = value;
        }else {
            valueHolder = new ValueHolder();
            valueHolder.value = value;
            valueHolder.expireTime = millSecond;
            valueHolder.modifyTime = new Date();
        }
        return (valueHolder = LOCAL_CACHE.put(key, valueHolder)) == null ? null : valueHolder.value;
    }

    /**
     * 存储Key,value,并指定过期时间. 刷新过期时间
     *
     * @param key
     * @param value
     * @param millSecond
     * @return
     */
    public static String putAndUpdateExpireTime(String key, String value, long millSecond){
        removeExpireKey(key);
        ValueHolder valueHolder = new ValueHolder();
        valueHolder.value = value;
        valueHolder.modifyTime = new Date();
        valueHolder.expireTime = millSecond;
        ValueHolder oldHolder = LOCAL_CACHE.put(key, valueHolder);
        return oldHolder != null ? oldHolder.value : null;
    }

    /**
     * 添加不过期的key
     *
     * @param key
     * @param value
     * @return
     */
    public static String put(String key, String value) {
        return putAndUpdateExpireTime(key, value, NO_EXPIRE_TIME);
    }

    /**
     * 删除key
     *
     * @param key
     * @return
     */
    public static String remove(String key) {
        ValueHolder valueHolder;
        return (valueHolder = LOCAL_CACHE.remove(key)) == null ? null : valueHolder.value;
    }

    /**
     * 获取key
     *
     * @param key
     * @return
     */
    public static String get(String key) {
        removeExpireKey(key);
        ValueHolder valueHolder;
        return (valueHolder = LOCAL_CACHE.get(key)) == null ? null : valueHolder.value;
    }

    /**
     * 获取,如果不存在,则返回默认值
     *
     * @param key
     * @param defaultValue
     * @return
     */
    public static String getOrDefault(String key, String defaultValue) {
        removeExpireKey(key);
        ValueHolder valueHolder;
        return (valueHolder = LOCAL_CACHE.get(key)) == null ? defaultValue : valueHolder.value;
    }

}

http://www.niftyadmin.cn/n/3682141.html

相关文章

【Java基础】之集合

集合 集合继承图 Collection 继承图 常用方法 1. add:添加元素 2. remove:删除指定元素&#xff0c;或指定下标。重载&#xff1b; 3. contains&#xff1a;查找指定元素是否存在 4. size&#xff1a;获取元素的个数 5. isEmpty:判断集合是否为空&#xff1b; 6. clear&…

洛谷P1147连续自然数和

采用前缀和思想&#xff0c;用二分查找寻找区间&#xff0c;时间复杂度O(nnlogn) #include<bits/stdc.h> #define maxn 2000000 using namespace std; long long arr[maxn1]; long long brr[maxn1]; int main() {brr[0]0;for(int i1;i<maxn;i){arr[i]i;brr[i]brr[i-1]…

ASP.NET:使用web.config文件进行配置

web.config配置文件中所有的配置设置都应该位于 <configuration> <system.web> 和 </system.web> </configuration> 之间. web.config的设置对于整个应用程序起作用&#xff0c;同时程序中随时可以调用web.config中的节点设置及关键key的值。web.c…

python开发学习

Python开发学习 一、Linux基础 Linux安装&#xff0c;Linux基本命令&#xff0c;Linux文件系统&#xff0c;Linux权限管理&#xff0c;Linux用户管理&#xff0c;Linux编辑器vim&#xff0c;shell脚本&#xff0c;Linux防火墙&#xff0c;Linux-LNMP架构原理搭建。 二、Python基…

Global.asax文件中触发那些事件

Application对象创建和结束时所触发的事件有    Application_Start    Application_End   Session对象创建和结束时所触发的事件有    Session_Start    Session_End   对程序有请求发生时触发的事件有 (按发生顺序排列)    Application_BeginRequest    Appli…

【JVM】之类加载子系统

Java & JVM Java是跨平台的语言&#xff0c;JVM是跨语言的平台。 Java【write once&#xff0c;run anywhere】一次编译到处运行。由于Java经过前端编译器[Javac]生成的是字节码class文件&#xff0c;而这个class文件在不同平台的虚拟机都是可以运行的&#xff0c;这也就…

数据集 (ADO.NET)

数据集 (ADO.NET)DataSet 对象对于支持 ADO.NET 中的断开连接的分布式数据方案起到至关重要的作用。 DataSet 是数据驻留在内存中的表示形式&#xff0c;不管数据源是什么&#xff0c;它都可提供一致的关系编程模型。它可以用于多种不同的数据源&#xff0c;用于 XML 数据&…

【JVM】之运行时数据区 Runtime Data Areas

Runtime Data Areas 官方文档&#xff1a;https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-2.html#jvms-2.5 概述 官方解释 The Java Virtual Machine defines various run-time data areas that are used during execution of a program. Some of these data areas…