zoukankan      html  css  js  c++  java
  • jodd-cache集锦

    Jodd cache提供了一组cache的实现,其层次如下:

    其中,

    AbstractCacheMap是一个具有计时和大小的缓存map的默认实现,它的实现类必须:

      创建一个新的缓存map。

      实现自己的删除(prune)策略。

    内部使用ReentranReadWriteLock来同步。因为从一个读锁升级到一个写锁是不可能的,因此在get(Object)方法内要注意。

    FIFOCach:先进先出缓存。优点是简单高效。缺点是不灵活,没有在内存中保存常用的缓存对象。

    /**
         * Creates a new LRU cache.
         */
        public FIFOCache(int cacheSize, long timeout) {
            this.cacheSize = cacheSize;
            this.timeout = timeout;
            cacheMap = new LinkedHashMap<K,CacheObject<K,V>>(cacheSize + 1, 1.0f, false);
        }
    
    
        // ---------------------------------------------------------------- prune
    
        /**
         * Prune expired objects and, if cache is still full, the first one.
         */
        @Override
        protected int pruneCache() {
            int count = 0;
            CacheObject<K,V> first = null;
            Iterator<CacheObject<K,V>> values = cacheMap.values().iterator();
            while (values.hasNext()) {
                CacheObject<K,V> co = values.next();
                if (co.isExpired() == true) {
                    values.remove();
                    count++;
                }
                if (first == null) {
                    first = co;
                }
            }
            if (isFull()) {
                if (first != null) {
                    cacheMap.remove(first.key);
                    count++;
                }
            }
            return count;
        }

    LFUCache:最少访问次数缓存。优点是常用缓存保留在内存中,偶然会使扫描算法失效。缺点是大的获取消耗即这个算法不能快速适应变化的使用模式,特别是集群的临时获取是无效的。

    public LFUCache(int maxSize, long timeout) {
            this.cacheSize = maxSize;
            this.timeout = timeout;
            cacheMap = new HashMap<K, CacheObject<K,V>>(maxSize + 1);
        }
    
        // ---------------------------------------------------------------- prune
    
        /**
         * Prunes expired and, if cache is still full, the LFU element(s) from the cache.
         * On LFU removal, access count is normalized to value which had removed object.
         * Returns the number of removed objects.
         */
        @Override
        protected int pruneCache() {
            int count = 0;
            CacheObject<K,V> comin = null;
    
            // remove expired items and find cached object with minimal access count
            Iterator<CacheObject<K,V>> values = cacheMap.values().iterator();
            while (values.hasNext()) {
                CacheObject<K,V> co = values.next();
                if (co.isExpired() == true) {
                    values.remove();
                    onRemove(co.key, co.cachedObject);
                    count++;
                    continue;
                }
                
                if (comin == null) {
                    comin = co;
                } else {
                    if (co.accessCount < comin.accessCount) {
                        comin = co;
                    }
                }
            }
    
            if (isFull() == false) {
                return count;
            }
    
            // decrease access count to all cached objects
            if (comin != null) {
                long minAccessCount = comin.accessCount;
    
                values = cacheMap.values().iterator();
                while (values.hasNext()) {
                    CacheObject<K, V> co = values.next();
                    co.accessCount -= minAccessCount;
                    if (co.accessCount <= 0) {
                        values.remove();
                        onRemove(co.key, co.cachedObject);
                        count++;                    
                    }
                }
            }
            return count;
        }

    LRUCache:最近未访问缓存。缓存对象的消耗是一个常量。简单高效,比FIFO更适应一个变化的场景。缺点是可能会被不会重新访问的缓存占满空间,特别是在面对获取类型扫描时则完全不起作用。然后它是目前最常用的缓存算法。

    /**
         * Creates a new LRU cache.
         */
        public LRUCache(int cacheSize, long timeout) {
            this.cacheSize = cacheSize;
            this.timeout = timeout;
            cacheMap = new LinkedHashMap<K, CacheObject<K,V>>(cacheSize + 1, 1.0f, true) {
                @Override
                protected boolean removeEldestEntry(Map.Entry eldest) {
                    return LRUCache.this.removeEldestEntry(size());
                }
            };
        }
    
        /**
         * Removes the eldest entry if current cache size exceed cache size.
         */
        protected boolean removeEldestEntry(int currentSize) {
            if (cacheSize == 0) {
                return false;
            }
            return currentSize > cacheSize;
        }
    
        // ---------------------------------------------------------------- prune
    
        /**
         * Prune only expired objects, <code>LinkedHashMap</code> will take care of LRU if needed.
         */
        @Override
        protected int pruneCache() {
            if (isPruneExpiredActive() == false) {
                return 0;
            }
            int count = 0;
            Iterator<CacheObject<K,V>> values = cacheMap.values().iterator();
            while (values.hasNext()) {
                CacheObject<K,V> co = values.next();
                if (co.isExpired() == true) {
                    values.remove();
                    count++;
                }
            }
            return count;
        }

    TimedCache 不限制大小,只有当对象过期时才会删除。标准的chache方法不会显式的调用删除(prune),而是根据定义好的延迟进行定时删除。

    public TimedCache(long timeout) {
            this.cacheSize = 0;
            this.timeout = timeout;
            cacheMap = new HashMap<K, CacheObject<K,V>>();
        }
    
        // ---------------------------------------------------------------- prune
    
        /**
         * Prunes expired elements from the cache. Returns the number of removed objects.
         */
        @Override
        protected int pruneCache() {
            int count = 0;
            Iterator<CacheObject<K,V>> values = cacheMap.values().iterator();
            while (values.hasNext()) {
                CacheObject co = values.next();
                if (co.isExpired() == true) {
                    values.remove();
                    count++;
                }
            }
            return count;
        }
    
    
        // ---------------------------------------------------------------- auto prune
    
        protected Timer pruneTimer;
    
        /**
         * Schedules prune.
         */
        public void schedulePrune(long delay) {
            if (pruneTimer != null) {
                pruneTimer.cancel();
            }
            pruneTimer = new Timer();
            pruneTimer.schedule(
                    new TimerTask() {
                        @Override
                        public void run() {
                            prune();
                        }
                    }, delay, delay
            );
        }
    
        /**
         * Cancels prune schedules.
         */
        public void cancelPruneSchedule() {
            if (pruneTimer != null) {
                pruneTimer.cancel();
                pruneTimer = null;
            }
        }

    注意,还提供了一个FileLFUCache,没有继承AbstractCacheMap.用LFU将文件缓存到内存,极大加快访问常用文件的性能。

        protected final LFUCache<File, byte[]> cache;
        protected final int maxSize;
        protected final int maxFileSize;
    
        protected int usedSize;
    
        /**
         * Creates file LFU cache with specified size. Sets
         * {@link #maxFileSize max available file size} to half of this value.
         */
        public FileLFUCache(int maxSize) {
            this(maxSize, maxSize / 2, 0);
        }
    
        public FileLFUCache(int maxSize, int maxFileSize) {
            this(maxSize, maxFileSize, 0);
        }
    
        /**
         * Creates new File LFU cache.
         * @param maxSize total cache size in bytes
         * @param maxFileSize max available file size in bytes, may be 0
         * @param timeout timeout, may be 0
         */
        public FileLFUCache(int maxSize, int maxFileSize, long timeout) {
            this.cache = new LFUCache<File, byte[]>(0, timeout) {
                @Override
                public boolean isFull() {
                    return usedSize > FileLFUCache.this.maxSize;
                }
    
                @Override
                protected void onRemove(File key, byte[] cachedObject) {
                    usedSize -= cachedObject.length;
                }
    
            };
            this.maxSize = maxSize;
            this.maxFileSize = maxFileSize;
        }
    
        // ---------------------------------------------------------------- get
    
        /**
         * Returns max cache size in bytes.
         */
        public int getMaxSize() {
            return maxSize;
        }
    
        /**
         * Returns actually used size in bytes.
         */
        public int getUsedSize() {
            return usedSize;
        }
    
        /**
         * Returns maximum allowed file size that can be added to the cache.
         * Files larger than this value will be not added, even if there is
         * enough room.
         */
        public int getMaxFileSize() {
            return maxFileSize;
        }
    
        /**
         * Returns number of cached files.
         */
        public int getCachedFilesCount() {
            return cache.size();
        }
    
        /**
         * Returns timeout.
         */
        public long getCacheTimeout() {
            return cache.getCacheTimeout();
        }
    
        /**
         * Clears the cache.
         */
        public void clear() {
            cache.clear();
            usedSize = 0;
        }
    
        // ---------------------------------------------------------------- get
    
        public byte[] getFileBytes(String fileName) throws IOException {
            return getFileBytes(new File(fileName));
        }
    
        /**
         * Returns cached file bytes.
         */
        public byte[] getFileBytes(File file) throws IOException {
            byte[] bytes = cache.get(file);
            if (bytes != null) {
                return bytes;
            }
    
            // add file
            bytes = FileUtil.readBytes(file);
    
            if ((maxFileSize != 0) && (file.length() > maxFileSize)) {
                // don't cache files that size exceed max allowed file size
                return bytes;
            }
    
            usedSize += bytes.length;
    
            // put file into cache
            // if used size > total, purge() will be invoked
            cache.put(file, bytes);
    
            return bytes;
        }
  • 相关阅读:
    python random模块随机取list中的某个值
    初学习-python打印乘法表、正方形、三角形
    python字符串拼接相关
    导航条2-
    HTML输入验证提示信息
    CMD常用功能
    AngularJs学习笔记(4)——自定义指令
    AngularJs学习笔记(3)——scope
    AngularJs学习笔记(2)——ng-include
    AngularJs学习笔记(1)——ng-app
  • 原文地址:https://www.cnblogs.com/davidwang456/p/4650755.html
Copyright © 2011-2022 走看看