常用的网站建设程序有哪些/新浪网今日乌鲁木齐新闻
前言
先来说一下自定义缓存的实现思路,首先需要定义一个存放缓存值的实体类,这个类里包含了缓存的相关信息,比如缓存的 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;@Overridepublic int compareTo(CacheValue o) {return hitCount.compareTo(o.hitCount);}
}
2、定义过期缓存检测类的代码如下:
import java.util.concurrent.TimeUnit;/*** 过期缓存检测线程*/
public class ExpireThread implements Runnable {@Overridepublic 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-lang3if (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(kreturn 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);}
}