Java實現本地緩存


本地緩存的作用:

 

0.基於LinkedHashMap實現LRU

 1) 構造LRUMap類,重寫LinkedHashMap中removeEldestEntry方法; 新增元素的時候,會判斷當前map大小是否超過DEFAULT_MAX_CAPACITY,超過則移除map中最老的節點;

 2)LinkedHashMap線程不安全,再插入刪除元素時使用顯示讀寫鎖ReentrantReadWriteLock

 3) 使用ScheduledExecutorService作為定時器,其具有一個schedule()方法,可以傳入一個Runnable實例,和一個定時時長 => 每次新插入的時候都建立一個schedule,以key為標識,過了指定時間后,進行刪除key,以實現LRU算法

 

package demo.shaw.common;

import java.util.LinkedHashMap;
import java.util.Map;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

public class LocalCache {
    private static final Map<String, Object> map;
    private static final ScheduledExecutorService timerService;  //定時器

    /**
     * 默認有效時長
     */
    private static final long DEFAULT_TIMEOUT = 3600;
    private static final long SECOND_TIME = 1000;

    /**
     * 初始化塊總是在構造器之前執行
     * 靜態初始化塊執行的優先級高於非靜態初始化塊,在對象裝載到JVM中時執行一次,僅能初始化類成員變量,即static修飾的數據成員
     * 靜態初始化塊是類相關的,系統將在類加載時執行靜態初始化塊,而不是在創建對象時才執行,因此靜態初始化塊總是比非靜態初始化塊先執行
     */
    static {
        map = new LRUMap<>();
        timerService = new ScheduledThreadPoolExecutor(1, new LocalCache.DaemonThreadFactory());
    }

    /**
     * 工具類
     */
    private LocalCache() {
    }

    static class LRUMap<K, V> extends LinkedHashMap<K, V> {
        /**
         * 默認緩存大小
         */
        private static final int DEFAULT_INITIAL_CAPACITY = 1 << 4;

        /**
         * 默認最大緩存大小
         */
        private static final int DEFAULT_MAX_CAPACITY = 1 << 30;

        /**
         * 默認加載因子
         */
        private static final float DEFAULT_LOAD_FACTOR = 0.75f;

        /**
         * 讀寫鎖
         */
        private ReadWriteLock readWriteLock = new ReentrantReadWriteLock();

        private final Lock rLock = readWriteLock.readLock();
        private final Lock wLock = readWriteLock.writeLock();


        public LRUMap() {
            super(DEFAULT_INITIAL_CAPACITY, DEFAULT_LOAD_FACTOR);
        }

        public LRUMap(int initialCapacity) {
            super(initialCapacity, DEFAULT_LOAD_FACTOR);
        }

        /**
         * 需要重寫LinkedHashMap中removeEldestEntry方法;
         * 新增元素的時候,會判斷當前map大小是否超過DEFAULT_MAX_CAPACITY,超過則移除map中最老的節點;
         * @param eldest
         * @return
         */
        protected boolean removeEldestEntry(Map.Entry<K,V> eldest) {
            return size() > DEFAULT_MAX_CAPACITY;
        }

        public V put(K k, V v) {
            wLock.lock();
            try {
                return super.put(k, v);
            } finally {
                wLock.unlock();
            }
        }

        public V get(String k) {
            rLock.lock();
            try {
                return super.get(k);
            } finally {
                rLock.unlock();
            }
        }

        public void putAll(Map<? extends K, ? extends V> m) {
            wLock.lock();
            try {
                super.putAll(m);
            } finally {
                wLock.unlock();
            }
        }

        public V remove(Object k) {
            wLock.lock();
            try {
                return super.remove(k);
            } finally {
                wLock.unlock();
            }
        }


        public boolean containKey(K k) {
            rLock.lock();
            try {
                return super.containsKey(k);
            } finally {
                rLock.unlock();
            }
        }

        public int size() {
            rLock.lock();
            try {
                return super.size();
            } finally {
                rLock.unlock();
            }
        }


        public void clear() {
            wLock.lock();
            try {
                super.clear();
            } finally {
                wLock.unlock();
            }
        }
    }

    /**
     * 清除緩存的任務類
     */
    static class CleanWorkerTask implements Runnable {
        private String key;

        public CleanWorkerTask(String key) {
            this.key = key;
        }

        @Override
        public void run() {
            LocalCache.remove(key);
        }
    }

    private static final class DaemonThreadFactory implements ThreadFactory {
        private AtomicInteger atomicInteger = new AtomicInteger(0);

        @Override
        public Thread newThread(Runnable runnable) {
            Thread thread = new Thread(runnable);
            thread.setName("schedule-pool-Thread-" + atomicInteger.getAndIncrement());
            thread.setDaemon(true);
            return null;
        }
    }


    /**
     * 增加緩存
     */
    public static void add(String key, Object value) {
        map.put(key, value);
        timerService.schedule(new CleanWorkerTask(key), DEFAULT_TIMEOUT, TimeUnit.MILLISECONDS);
    }

    /**
     * 增加緩存
     * @param timeout  有效時長
     */
    public static void add(String key, Object value, int timeout) {
        map.put(key, value);
        timerService.schedule(new CleanWorkerTask(key), timeout * SECOND_TIME, TimeUnit.MILLISECONDS);
    }

    public static void putAll(Map<String, Object> m, int timeout) {
        map.putAll(m);
        for (String key : m.keySet()) {
            timerService.schedule(new CleanWorkerTask(key), timeout * SECOND_TIME, TimeUnit.MILLISECONDS);
        }
    }


    /**
     * 獲取緩存
     */
    public static Object get(String key) {
        return map.get(key);
    }

    public static boolean containsKey(String key) {
        return map.containsKey(key);
    }

    /**
     *
     * @param key
     */
    public static void remove(String key) {
        map.remove(key);
    }

    public static int size() {
        return map.size();
    }

}
View Code

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM