LRUCache , LFUCach 实现源码 案例

1.缓存工具类  LRUCache<K, V>

package com.linyang.cache;

import java.util.concurrent.ConcurrentHashMap;

/**
 * 本地缓存工具类
 * LRU
 */
public class LRUCache<K, V> {

    private class Node{
        Node prev;
        Node next;
        Object key;
        Object value;

        public Node(Object key, Object value) {
            this.key = key;
            this.value = value;
            this.prev = null;
            this.next = null;
        }
    }


    private int capacity;

    private ConcurrentHashMap<Object, Node> concurrentHashMap;

    private Node head = new Node(-1, -1);
    private Node tail = new Node(-1, -1);

    public LRUCache(int capacity) {
        // write your code here
        this.capacity = capacity;
        this.concurrentHashMap = new ConcurrentHashMap<>(capacity);
        tail.prev = head;
        head.next = tail;
    }

    /**
     * 获取缓存
     *
     * @param key
     * @return
     */
    public Object get(K key) {
        checkNotNull(key);
        if (concurrentHashMap.isEmpty()) return null;
        if (!concurrentHashMap.containsKey(key)) return null;
        Node current = concurrentHashMap.get(key);
        // 将当前链表移出
        current.prev.next = current.next;
        current.next.prev = current.prev;

        move_to_tail(current);

        return current.value;
    }

    /**
     * 添加缓存
     *
     * @param key
     * @param value
     */
    public void put(K key, V value) {
        checkNotNull(key);
        checkNotNull(value);
        // 当缓存存在时,更新缓存
        if (concurrentHashMap.containsKey(key)){
            Node current = concurrentHashMap.get(key);
            // 将当前链表移出
            current.prev.next = current.next;
            current.next.prev = current.prev;

            move_to_tail(current);
            return;
        }
        // 已经达到最大缓存
        if (isFull()) {
            concurrentHashMap.remove(head.next.key);
            head.next.next.prev = head;
            head.next = head.next.next;
        }
        Node node = new Node(key,value);
        concurrentHashMap.put(key,node);
        move_to_tail(node);
    }

    /**
     * 检测字段是否合法
     *
     * @param reference
     * @param <T>
     * @return
     */
    public static <T> T checkNotNull(T reference) {
        if (reference == null) {
            throw new NullPointerException();
        }
        return reference;
    }

    /**
     * 判断是否达到最大缓存
     *
     * @return
     */
    private boolean isFull() {
        return concurrentHashMap.size() == capacity;
    }

    private void move_to_tail(Node current) {
        // 将当前链表添加到尾部
        tail.prev.next = current;
        current.prev = tail.prev;
        tail.prev = current;
        current.next = tail;
    }

}

  

2.缓存工具类  LFUCache<K, V>

package com.linyang.cache;

import java.util.Collections;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;

/**
 * 本地缓存工具类
 */
public class LFUCache<K, V> {

    private ConcurrentHashMap<Object, Cache> concurrentHashMap;

    final int size;


    public LFUCache(int capacity) {
        this.size = capacity;
        this.concurrentHashMap = new ConcurrentHashMap<>(capacity);
        new Thread(new TimeoutTimerThread()).start();
    }

    /**
     * 获取缓存
     *
     * @param key
     * @return
     */
    public Object get(K key) {
        checkNotNull(key);
        if (concurrentHashMap.isEmpty()) return null;
        if (!concurrentHashMap.containsKey(key)) return null;
        Cache cache = concurrentHashMap.get(key);
        if (cache == null) return null;
        cache.setHitCount(cache.getHitCount()+1);
        cache.setAccessTime(System.currentTimeMillis());
        return cache.getValue();
    }

    /**
     * 添加缓存
     *
     * @param key
     * @param value
     */
    public void put(K key, V value,long expire) {
        checkNotNull(key);
        checkNotNull(value);
        // 当缓存存在时,更新缓存
        if (concurrentHashMap.containsKey(key)){
            Cache cache = concurrentHashMap.get(key);
            cache.setHitCount(cache.getHitCount()+1);
            cache.setWriteTime(System.currentTimeMillis());
            cache.setAccessTime(System.currentTimeMillis());
            cache.setExpireTime(expire);
            cache.setValue(value);
            return;
        }
        // 已经达到最大缓存
        if (isFull()) {
            Object kickedKey = getKickedKey();
            if (kickedKey !=null){
                // 移除最少使用的缓存
                concurrentHashMap.remove(kickedKey);
            }else {
                return;
            }
        }
        Cache cache = new Cache();
        cache.setKey(key);
        cache.setValue(value);
        cache.setWriteTime(System.currentTimeMillis());
        cache.setAccessTime(System.currentTimeMillis());
        cache.setHitCount(1);
        cache.setExpireTime(expire);
        concurrentHashMap.put(key, cache);
    }

    /**
     * 检测字段是否合法
     *
     * @param reference
     * @param <T>
     * @return
     */
    public static <T> T checkNotNull(T reference) {
        if (reference == null) {
            throw new NullPointerException();
        }
        return reference;
    }

    /**
     * 判断是否达到最大缓存
     *
     * @return
     */
    private boolean isFull() {
        return concurrentHashMap.size() == size;
    }

    /**
     * 获取最少使用的缓存
     * @return
     */
    private Object getKickedKey() {
        Cache min = Collections.min(concurrentHashMap.values());
        return min.getKey();
    }




    /**
     * 处理过期缓存
     */
    class TimeoutTimerThread implements Runnable {
        public void run() {
            while (true) {
                try {
                    TimeUnit.SECONDS.sleep(60);
                    expireCache();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }

        /**
         * 创建多久后,缓存失效
         *
         * @throws Exception
         */
        private void expireCache() throws Exception {
            System.out.println("检测缓存是否过期缓存");
            for (Object key : concurrentHashMap.keySet()) {
                Cache cache = concurrentHashMap.get(key);
                long timoutTime = TimeUnit.NANOSECONDS.toSeconds(System.nanoTime()
                        - cache.getWriteTime());
                if (cache.getExpireTime() > timoutTime) {
                    continue;
                }
                System.out.println(" 清除过期缓存 : " + key);
                //清除过期缓存
                concurrentHashMap.remove(key);
            }
        }
    }

}

  

main方法

package com.linyang.cache;

/**
 * localcache
 * 
 * @author YinTao
 * 2020-03-24
 */
public class app {
    public static void main(String[] args) throws Exception {
////        LFUCache localCache = new LFUCache();
////        localCache.put("key", "66666");
////        System.out.println(localCache.get("key"));
////        TimeUnit.SECONDS.sleep(6);
////        System.out.println("清除缓存后:"+localCache.get("key"));
//
//        FileWriter writer = new FileWriter("txt.txt");
//        BufferedWriter bufferedWriter = new BufferedWriter(writer);
////        for(int i = 0;i<5;i++){
////            bufferedWriter.write("");
//        bufferedWriter.write("哈哈哈哈哈\n哈哈哈哈哈\n哈哈哈哈哈\n哈哈哈哈哈\n哈哈哈哈哈\n");
//        bufferedWriter.newLine();
//        bufferedWriter.flush();
//
//
////        }
//        LFUCache localCache = new LFUCache(3);
//        for (int i = 0; i < 3; i++) {
//            localCache.put("01"+i, "张三"+i,2*60);
//        }
//        localCache.get("010");
//        localCache.get("011");
//        localCache.get("010");
//        localCache.put("013","李四",2*60);
//
//        for (int i = 0; i < 4; i++) {
//            System.out.println(localCache.get("01"+i));
//        }

        LRUCache lruCache = new LRUCache(6);
//        for (int i = 0; i < 5; i++) {
//            lruCache.put("lru"+i, "张三"+i);
//        }
        lruCache.put(123, "{0x00, 0x10, 0x02, 0x00}");
        lruCache.put("lru5","李四");

//        for (int i = 0; i < 6; i++) {
//            System.out.println(lruCache.get("lru"+i));
//        }
        System.out.println(lruCache.get("lru5"));
        System.out.println(lruCache.get(123));
    }
}

猜你喜欢

转载自www.cnblogs.com/adao21/p/12560711.html