欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

自定义缓存

程序员文章站 2022-05-19 15:40:26
...

前言

先来说一下自定义缓存的实现思路,首先需要定义一个存放缓存值的实体类,这个类里包含了缓存的相关信息,比如缓存的 key 和 value,缓存的存入时间、最后使用时间和命中次数(预留字段,用于支持 LFU 缓存淘汰),再使用 ConcurrentHashMap 保存缓存的 key 和 value 对象(缓存值的实体类),然后再新增一个缓存操作的工具类,用于添加和删除缓存,最后再缓存启动时,开启一个无限循环的线程用于检测并删除过期的缓存,实现代码如下。

1、首先,定义一个缓存值实体类,代码如下:

import lombok.Getter;
import lombok.Setter;

/**
 * 缓存实体类
 */
@Getter
@Setter
public class CacheValue implements Comparable<CacheValue> {
    // 缓存键
    private Object key;
    // 缓存值
    private Object value;
    // 最后访问时间
    private long lastTime;
    // 创建时间
    private long writeTime;
    // 存活时间
    private long expireTime;
    // 命中次数
    private Integer hitCount;

    @Override
    public int compareTo(CacheValue o) {
        return hitCount.compareTo(o.hitCount);
    }
}

2、定义过期缓存检测类的代码如下:

import java.util.concurrent.TimeUnit;

/**
 * 过期缓存检测线程
 */
public class ExpireThread implements Runnable {
    @Override
    public void run() {
        while (true) {
            try {
                // 每十秒检测一次
                TimeUnit.SECONDS.sleep(10);
                // 缓存检测和清除的方法
                expireCache();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 缓存检测和清除的方法
     */
    private void expireCache() {
        System.out.println("检测缓存是否过期缓存");
        for (String key : CacheGlobal.concurrentMap.keySet()) {
            MyCache cache = CacheGlobal.concurrentMap.get(key);
            // 当前时间 - 写入时间
            long timoutTime = TimeUnit.NANOSECONDS.toSeconds(
                    System.nanoTime() - cache.getWriteTime());
            if (cache.getExpireTime() > timoutTime) {
                // 没过期
                continue;
            }
            // 清除过期缓存
            CacheGlobal.concurrentMap.remove(key);
        }
    }
}

3、接着,我们要新增一个缓存操作的工具类,用于查询和存入缓存,实现代码如下:

import org.apache.commons.lang3.StringUtils;

import java.util.concurrent.TimeUnit;

/**
 * 缓存操作工具类
 */
public class CacheUtils {

    /**
     * 添加缓存
     * @param key
     * @param value
     * @param expire
     */
    public void put(String key, Object value, long expire) {
        // 非空判断,借助 commons-lang3
        if (StringUtils.isBlank(key)) return;
        // 当缓存存在时,更新缓存
        if (CacheGlobal.concurrentMap.containsKey(key)) {
            MyCache cache = CacheGlobal.concurrentMap.get(key);
            cache.setHitCount(cache.getHitCount() + 1);
            cache.setWriteTime(System.currentTimeMillis());
            cache.setLastTime(System.currentTimeMillis());
            cache.setExpireTime(expire);
            cache.setValue(value);
            return;
        }
        // 创建缓存
        MyCache cache = new MyCache();
        cache.setKey(key);
        cache.setValue(value);
        cache.setWriteTime(System.currentTimeMillis());
        cache.setLastTime(System.currentTimeMillis());
        cache.setHitCount(1);
        cache.setExpireTime(expire);
        CacheGlobal.concurrentMap.put(key, cache);
    }

    /**
     * 获取缓存
     * @param key
     * @return
     */
    public Object get(String key) {
        // 非空判断
        if (StringUtils.isBlank(key)) return null;
        // 字典中不存在
        if (CacheGlobal.concurrentMap.isEmpty()) return null;
        if (!CacheGlobal.concurrentMap.containsKey(key)) return null;
        MyCache cache = CacheGlobal.concurrentMap.get(key);
        if (cache == null) return null;
        // 惰性删除,判断缓存是否过期
        long timoutTime = TimeUnit.NANOSECONDS.toSeconds(
                System.nanoTime() - cache.getWriteTime());
        // 缓存过期
        if (cache.getExpireTime() <= timoutTime) {
            // 清除过期缓存
            CacheGlobal.concurrentMap.remove(k
            return null;
        }
        cache.setHitCount(cache.getHitCount() + 1);
        cache.setLastTime(System.currentTimeMillis());
        return cache.getValue();
    }
}

4、最后是调用缓存的测试代码:

public class MyCacheTest {
    public static void main(String[] args) {
        CacheUtils cache = new CacheUtils();
        // 存入缓存
        cache.put("key", "老王", 10);
        // 查询缓存
        String val = (String) cache.get("key");
        System.out.println(val);
        // 查询不存在的缓存
        String noval = (String) cache.get("noval");
        System.out.println(noval);
    }
}

 

相关标签: 缓存 java