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;
    }
时间: 2024-11-10 21:21:29

jodd-cache集锦的相关文章

『fedora奇葩问题集锦』Malformed lock file found: /var/cache/dnf/metadata_lock.pid.

Malformed lock file found: /var/cache/dnf/metadata_lock.pid.Ensure no other dnf process is running and remove the lock file manually or run systemd-tmpfiles --remove dnf.conf.[[email protected] ajaxGu]# systemd-tmpfiles --remove dnf.conf 英文不好看不懂的有木有,

使用缓存cache 的大坑

"-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> 使用缓存cache 的大坑 - Mr_Smile2014的博客 - 博客频道 - CSDN.NET Mr_Smile2014的博客 目录视图 摘要视图 订阅 [活动]2017 CSDN博客专栏评选 &nbsp [5月书讯]流畅的Python,终于等到你!    &am

2019阿里巴巴面试题集锦(有答案哦),收藏!

来源商业新知网,原标题:[收藏]2019阿里巴巴面试题集锦(含答案) [导读] 本文是阿里巴巴 2019 面试题集锦(含答案),是阿里巴巴自身技术专家们结合多年的工作.面试经验总结提炼而成的面试真题.通过这些面试题,还可以间接地了解技术大牛们出题思路与考察要点. 想要入职大厂可谓是千军万马过独木桥. 要通过层层考验, 刷题 肯定是必不可少的. 为帮助开发者们提升面试技能.有机会入职阿里,云栖社区特别制作了这个专辑—— 阿里巴巴资深技术专家们结合多年的工作.面试经验总结提炼而成的面试真题 这一次整

13 Zabbix4.4.0系统告警“More than 75% used in the configuration cache”

点击返回:自学Zabbix之路 点击返回:自学Zabbix4.0之路 点击返回:自学zabbix集锦 13 Zabbix4.4.0系统告警“More than 75% used in the configuration cache” More than 75% used in the configuration cache, 可用的配置缓存超过75%. 解决办法: 更改默认缓存配置的大小.  默认CacheSize只有8M,可根据自己需求改大即可. systemctl restart zabbi

MyBatis面试题集锦(精选)

以下来自网络收集,找不到原文出处.此次主要为了面试准备收集,希望对大家有所帮助~~~~ 1. 简单谈一谈MyBatis? Mybatis是一个优秀的持久层框架,它对jdbc的操作数据库的过程进行封装,使得开发者只需要专注于SQL语句本身,而不用去关心注册驱动,创建connection等 Mybatis通过xml文件配置或者注解的方式将要执行的各种statement配置起来,并通过java对象和statement中的sql进行映射成最终执行的sql语句,最后由Mybatis框架执行sql并将结果映

centos7开机无法进入图形界面,出现sda assuming drive cache write through的一个解决方案

centos7开机无法进入图形界面,出现sda assuming drive cache write through.no valid rapl domains found in package之类信息. 这个问题是我在VMware里面操作出现的,原因是我在使用虚拟机和实体机之间文件共享功能时,centos系统无法出现hgfs文件夹, 为了解决hgfs的不出现问题,我参考了如下帖子: http://blog.csdn.net/cindy_cheng/article/details/5045697

Linux内存学习之buffer和cache的区别详解

本文和大家分享的主要是linux 中 内存buffer 和 cache 的区别相关内容,一起来看看吧,希望对大家 学习linux有所帮助. 细心的朋友会注意到, 当你在 linux 下频繁存取文件后 , 物理内存会很快被用光 , 当程序结束后 , 内存不会被正常释放 , 而是一直作为 caching. 这个问题 , 貌似有不少人在问 , 不过都没有看到有什么很好解决的办法 . 那么我来谈谈这个问题 . 先来说说free 命令 [[email protected] ~]# free -m tota

linux 清除内存和Cache方法

Linux下释放内存和缓存方法 $ free -m 运行sync将cache的内容写回硬盘 $ sync #格式:sync 强制将内存中的文件缓冲内容写到磁盘. 通过修改proc系统的drop_caches清理free的cache $ echo 3 > /proc/sys/vm/drop_caches $ free -m 仅清除页面缓存(PageCache) # echo 1 > /proc/sys/vm/drop_caches 清除目录项和inode # echo 2 > /proc/

Linux中的Buffer 与 Cache

A buffer is something that has yet to be "written" to disk.       A cache is something that has been "read" from the disk and stored for later use. 缓存(cache)是把读取过的数据保存起来,重新读取时若命中(找到需要的数据)就不要去读硬盘了,若没有命中就读硬盘.其中的数据会根据读取频率进行组织,把最频繁读取的内容放在最