• HashMap+线程池+优先队列实现带过期时间的LRUCache


    LRU算法

    Least Recently Used 意思是最近最少使用,是一种常用的置换算法,当你向一个队列或者其他容器中添加任务或者页面时容器已满,该算法会自动清理一个位置给你,今天我实现的就是添加了过期时间同时能够自动清理过期时间的LRU算法

    下面是实现和思路

    package interview;
    
    
    import java.util.*;
    import java.util.concurrent.ConcurrentHashMap;
    import java.util.concurrent.ScheduledThreadPoolExecutor;
    import java.util.concurrent.TimeUnit;
    
    /**
     * @ Author     :fqg
     * @ Date       :Created in 12:12 2020/8/25
     */
    public class TimeOutLRU {
        static class Node implements Comparable<Node>{
            String key;
            Object value;
            Long expireTime;
            public Node(){}
            public Node(String key, Object value, long expireTime){
                this.key = key;
                this.value = value;
                this.expireTime = expireTime;
            }
            //内比较器的重写
            @Override
            public int compareTo(Node o) {
                long l = this.expireTime - o.expireTime;
                if(l < 0) return -1;
                if(l > 0) return 1;
                return 0;
            }
        }
        //线程池中的worker线程
        static class ExpireThread implements Runnable{
    
            @Override
            public void run() {
                long now = System.currentTimeMillis();
                while (true) {
                    Node n = queue.peek();
                    if(n == null || n.expireTime > now) return;
                    queue.remove(n);
                    map.remove(n.key);
                    System.out.println("清除成功");
                }
            }
        }
        //内部容量,保证线程安全使用concurrentHashMap同时将queue设置成单例模式
        private static ConcurrentHashMap<String, Node> map;
        //使用优先队列,在队列内将Node进行排序
        private static volatile PriorityQueue<Node> queue;
        //线程池,这里使用定时任务线程池
        private static ScheduledThreadPoolExecutor pool = new ScheduledThreadPoolExecutor(10);
        //双从检查锁
        private PriorityQueue<Node> getInstance(){
            if(queue == null){
                synchronized(TimeOutLRU.class){
                    if(queue == null){
                        queue = new PriorityQueue<>(1024);
                    }
                }
            }
            return queue;
        }
        //constructor
        public TimeOutLRU(){
            map = new ConcurrentHashMap<>();
            queue = getInstance();
            //每隔三秒获取queue的头结点,查看是否过期。
            pool.scheduleWithFixedDelay(new ExpireThread(), 0, 3, TimeUnit.SECONDS);
        }
        //expose method
        public Object set(String key, Object value, long time){
            //获取过期时间
            long timeout = System.currentTimeMillis() + time;
            Node newNode = new Node(key, value, timeout);
            Node old = map.put(key, newNode);
            queue.offer(newNode);
            if(old != null){
                queue.remove(old);
                return old.value;
            }
            return null;
        }
    
        public Object get(String key){
            Node n = map.get(key);
            return n == null ? null : n.value;
        }
    
        public static void main(String[] args) throws InterruptedException {
            TimeOutLRU timeOutLRU = new TimeOutLRU();
            timeOutLRU.set("1","fqg",1000);
            Thread.sleep(1000);
            Object str = timeOutLRU.get("1");
            System.out.println(str);
        }
    }

     测试结果如下

    问题:

    1.实现思路总结

    重新定义个一个Node添加过期时间字段,使用优先队列和ConcurrentHashaMap来存值和过期检测,使用定时任务线程池来循环检测优先队列的头结点是否过期,如果过期就删除(实现过程中没有实现队列满了,或者其他特殊情况,当时我想的是如果队列满了,直接删除头结点就行,因为毕竟是个优先级队列,头结点的过期时间永远是最近的)

    2.Comparator和Comparable两个比较器的区别

    一个在内部使用一个在外部使用,用处不同意义相同但是体现的思想不同,内比较器体现的封装,外比较器体现的扩展。

  • 相关阅读:
    pip install报错:RuntimeError: Python version >= 3.5 required
    简明conda使用指南
    Ninja使用Visual Studio(cl.exe)构建
    cmake设定boost python3
    系统程序员成长计划——像机器一样思考(二)
    在Redis Sentinel环境下,jedis该如何配置
    如何用Go语言实现汉诺塔算法
    pt-online-schema-change的实现原理
    MySQL Sniffer
    如何利用docker快速构建MySQL主从复制环境
  • 原文地址:https://www.cnblogs.com/frank9571/p/13559544.html
Copyright © 2020-2023  润新知