开发者

Java使用map实现带过期时间的缓存机制

目录
  • 引言
  • 代码实现
  • 测试

引言

在 Java 开发领域,缓存机制的构建通常依赖于 Redis 等专业缓存数据库。这类解决方案虽能提供强大的缓存能力,但引入中间件意味着增加系统架构复杂度、部署成本与运维负担。本文将深入探讨一种轻量级替代方案 —— 基于 Java 原生Map实现的带过期时间的缓存机制。该方案无需引入外部工具,仅依托 Java 标准库即可快速搭建起缓存体系,特别适用于对资源占用敏感、架构追求极简的项目场景,为开发者提供了一种轻量高效的缓存数据管理新选择。

优点

  • 轻量便捷:无需引入 Redis 等外部中间件,直接使用 Java 标准库即可实现,降低了项目依赖,简化了部署流程。
  • 快速搭python建:基于熟悉的Map数据结构,开发人员能够快速理解和实现缓存逻辑,显著提升开发效率。
  • 资源可控:可灵活控制缓存数据的生命周期,通过设置过期时间,精准管理内存占用,适合对资源占用敏感的场景。

缺点:该方案存在明显局限性,即数据无法持久化。一旦应用程序停止运行,缓存中的所有数据都会丢失。相较于 Redis 等具备持久化功能的专业缓存数据库,在需要长期保存缓存数据,或是应对应用重启后数据恢复需求的场景下,基于 Java 原生Map的缓存机制http://www.devze.com就显得力不从心。

代码实现

package com.sunny.utils;

import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

public class SysCache {

    // 单例实例
    private static class Holder {
        private static final SysCache INSTANCE = new SysCache();
    }

    public static SysCache getInstance() {
        return Holder.INSTANCE;
    }

    // 缓存存储结构,Key为String,Value为包含值和过期时间的CacheEntry对象
    private final ConcurrentHashMap<String, CacheEntry> cacheMap = new ConcurrentHashMap<>();
    // 定时任务执行器
    private final ScheduledExecutorService  scheduledExecutorService;

    // 私有构造方法,初始化定时清理任务
    private SysCache() {
        scheduledExecutorService = Executors.newSingleThreadScheduledExecutor();
        // 每隔1秒执行一次清理任务
        scheduledExecutorService.scheduleAtFixedRate(this::cleanUp, 1, 1, TimeUnit.SECONDS);
        // 注册JVM关闭钩子以优雅关闭线程池
        Runtime.getRuntime().addShutdownHook(new Thread(this::shutdown));
    }

    /**
     * 存入缓存
     * @param key 键
     * @param value 值
     */
    public void set(String key, Object value){
        cacheMap.put(key, new CacheEntry(value, -1));
    }

    /**
     * 存入缓存
     * @param key 键
     * @param value 值
     * @param expireTime 过期时间,单位毫秒python
     */
    public void set(String key, Object value, long expireTime) {
        if (expireTime <= 0) {
            throw new IllegalArgumentException("expireTime must be greater than 0");
        }
        cacheMap.put(key, new CacheEntry(value, System.currentTimeMillis() + expireTime));
    }

    /**
     * 删除缓存
     * @param key 键
     */
    public void remove(String key) {
        cacheMap.remove(key);
    }

    /**
     * 缓存中是否包含键
     * @param key 键
     */
    public bojavascriptolean containsKey(String key) {
        CacheEntry cacheEntry = cacheMap.get(key);
        if (cacheEntry == null) {
            return false;
        }
        if (cacheEntry.getExpireTime() < System.currentTimeMillis()) {
            remove(key);
            return false;
        }
        return true;
    }


    /**
     *获取缓存值
     * @param key 键
     */
    public Object get(String key) {
        CacheEntry cacheEntry = cacheMap.get(key);
        if (cacheEntry == null) {
            return null;
        }
        if (cacheEntry.getExpireTime() < System.currentTimeMillis()) {
            cacheMap.remove(key);
            return null;
        }
        return cacheEntry.getValue();
    }


    private statichttp://www.devze.com class CacheEntry {
        private final Object value;
        private final long expireTime;

        public CacheEntry(Object value, long expireTime) {
            this.value = value;
            this.expireTime = expireTime;
        }

        public Object getValue() {
            return value;
        }

        public long getExpireTime() {
            return expireTime;
        }
    }

    /**
     * 定时清理过期条目
     */
    private void cleanUp() {
        Iterator<Map.Entry<String, CacheEntry>> iterator = cacheMap.entrySet().iterator();
        long currentTime = System.currentTimeMillis();
        while (iterator.hasNext()) {
            Map.Entry<String, CacheEntry> entry = iterator.next();
            CacheEntry cacheEntry = entry.getValue();
            if (cacheEntry.expireTime < currentTime) {
                // 使用iterator移除当前条目,避免ConcurrentModificationException
                iterator.remove();
            }
        }
    }

    /**
     * 关闭线程池释放资源
     */
    private void shutdown() {
        scheduledExecutorService.shutdown();
        try {
            if (!scheduledExecutorService.awaitTermination(5, TimeUnit.SECONDS)) {
                scheduledExecutorService.shutdownNow();
            }
        } catch (InterruptedException e) {
            scheduledExecutorService.shutdownNow();
            Thread.currentThread().interrupt();
        }
    }
}

测试

Java使用map实现带过期时间的缓存机制

如上图,缓存中放入一个值,过期时间为5秒,每秒循环获取1次,循环10次,过期后,获取的值为null

到此这篇关于Java使用map实现带过期时间的缓存机制的文章就介绍到这了,更多相关Java map过期时间缓存内容请搜索编程客栈(www.devze.com)以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程客栈(www.devze.com)!

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新开发

开发排行榜