基于Java实现本地缓存,缓存过期删除和LRU缓存淘汰

本文介绍了如何基于Java实现本地缓存,包括使用HashMap或ConcurrentHashMap作为数据存储,结合并发环境下的选择。讨论了缓存过期删除策略,借鉴Redis的定期删除和惰性删除,并提出实现一个监控线程或ScheduledExecutorService进行延迟删除。重点阐述了采用最近最少使用(LRU)缓存淘汰策略,需要维护元素使用队列,并提供了使用ReentrantLock+LinkedHashMap的实现方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

我们结合平常使用的Redis来想下,自己实现本地缓存需要考虑哪些因素呢,我这里总结了三点:

  • 数据存储,基于Java实现的话我首先想到的是key-value结构的集合,如HashMap,并发环境下的话使用ConcurrentHashMap、随着访问顺序元素位置会变化的LinkedHashMap
  • 缓存过期删除策略,参考Redis的定期删除和惰性删除
  • 缓存淘汰策略,有先进先出、最少使用、最近最少使用(LRU)、随机等策略。

由以上可知,

  • 要实现缓存过期删除的话,需要记录元素的生效时间,可以实现一个监控线程或用ScheduledExecutorService实现延迟删除。
  • 缓存淘汰策略采用最近最少使用(LRU)的话,需要维护一个元素的使用队列

实现方式需要涉及的Java类有两种方式:

  • ReentrantLock+ConcurrentHashMap + ConcurrentLinkedQueue
  • ReentrantLock+ LinkedHashMap(本文以这种方式实现)

详细实现代码见下,

public class LocalCache {

    //默认的缓存容量
    private static int DEFAULT_CAPACITY = 16;
    //最大容量
    private static int MAX_CAPACITY = 64;

    private ReentrantLock lock = new ReentrantLock();

    private static Map<String, CacheData> linkedHashMap = new LinkedHashMap<String, CacheData>(DEFAULT_CAPACITY, 0.75f, true) {
	
        @Override
        protected boolean removeEldestEntry(Map.Entry eldest) {
             //缓存淘汰
            return MAX_CAPACITY < linkedHashMap.size();
        }
    };


    private ScheduledExecutorService scheduledExecutorService = Executors.newSingleThreadScheduledExecutor();


    public void put(String key, String value, long expire) {
        lock.lock();
        try {
            CacheData data = new CacheData();
            data.setKey(key);
            data.setValue(value);
            data.setExpireTime(expire + System.currentTimeMillis());
            linkedHashMap.put(key, data);
            if (expire > 0) {
                removeAfterExpireTime(key, expire);
            }
        } finally {
            lock.unlock();
        }
    }


    /**
     * 过期删除
     */
    public CacheData get(String key) {
        lock.lock();
        try {
            return linkedHashMap.getOrDefault(key, new CacheData());
        } finally {
            lock.unlock();
        }
    }

    private void removeAfterExpireTime(String key, long expireTime) {
        scheduledExecutorService.schedule(() -> {
            System.out.println("过期后清除该键值对");
            linkedHashMap.remove(key);
        }, expireTime, TimeUnit.MILLISECONDS);
    }

    private LocalCache () {
    }

    private static class CacheLocal {
        private static LocalCache cache = new LocalCache ();
    }

    public static LocalCache getInstance() {
        return CacheLocal.cache;
    }


    private class CacheData {

        private String key;

        private String value;

        /**
         * 存活时间
         */
        private long expireTime;


        private String getValue() {
            return value;
        }

        private void setValue(String value) {
            this.value = value;
        }

        public String getKey() {
            return key;
        }

        public void setKey(String key) {
            this.key = key;
        }

        public long getExpireTime() {
            return expireTime;
        }

        public void setExpireTime(long expireTime) {
            this.expireTime = expireTime;
        }
    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值