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;
}

jodd-cache集锦的更多相关文章

  1. jodd cache实现缓存超时

    public class JoddCache { private static final int CACHE_SIZE = 2; private final static Cache<Obje ...

  2. 『奇葩问题集锦』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 a ...

  3. java jodd轻量级开发框架

    http://git.oschina.net/huangyong/jodd_demo/blob/master/jodd-example/src/main/java/jodd/example/servi ...

  4. 大型互联网架构概述 关于架构的架构目标 典型实现 DNS CDN LB WEB APP SOA MQ CACHE STORAGE

    大型互联网架构概述 目录 架构目标 典型实现 DNS CDN LB WEB APP SOA MQ CACHE STORAGE 本文旨在简单介绍大型互联网的架构和核心组件实现原理. 理论上讲,从安装配置 ...

  5. springboot项目部署到独立tomcat的爬坑集锦

    目录 集锦一:普通的springboot项目直接部署jar包 集锦二:springboot项目不能直接打war包部署 集锦三:因为tomcat版本问题导致的lombok插件报错:Invalid byt ...

  6. bug集锦------持续但不定期 更新

    对于个人而言:这个错误集锦是很有必要的. 为了避免误导他人,其中个人想法:用 紫色加粗 标注. 1.springboot端口冲突: Protocol handler start failed2.spr ...

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

    点击返回:自学Zabbix之路 点击返回:自学Zabbix4.0之路 点击返回:自学zabbix集锦 13 Zabbix4.4.1系统告警“More than 75% used in the conf ...

  8. Jodd - Java界的瑞士军刀轻量级工具包!

    Jodd介绍 Jodd是对于Java开发更便捷的开源迷你框架,包含工具类.实用功能的集合,总包体积不到1.7M. Jodd构建于通用场景使开发变得简单,但Jodd并不简单!它能让你把事情做得更好,实现 ...

  9. Redis面试题集锦(精选)

    1.什么是 Redis?简述它的优缺点? Redis的全称是:Remote Dictionary.Server,本质上是一个Key-Value 类型的内存数据库,很像memcached,整个数据库统统 ...

随机推荐

  1. eclipse C开发添加自己的头文件搜索路径

    eclipse编译C程序时提示: ..\src\main.c:8:21: fatal error: my_type.h: No such file or directory 如图: 需要添加自己的头文 ...

  2. shrio int配置

    之前章节我们已经接触过一些INI配置规则了,如果大家使用过如Spring之类的IoC/DI容器的话,Shiro提供的INI配置也是非常类似的,即可以理解为是一个IoC/DI容器,但是区别在于它从一个根 ...

  3. phpMyAdmin出现找不到mysql扩展和Cannot log in to the MySQL server问题

    环境:Centos6.5,Apache2.4, PHP5.5, MySql5.6. phpMyAdmin版本:https://files.phpmyadmin.net/phpMyAdmin/4.4.1 ...

  4. BZOJ 1103 DFS序+线段树

    思路: 先搞出来DFS序 进入这个点 +1 出这个点 -1 线段树维护前缀和 (因为还要修改) 搞定 修改的时候只修改底下节点就OK了 (边权–>点权 不多说) //By SiriusRen # ...

  5. java线程深入学习

    一.java中的线程是通过Thread类创建的, //下面是构造函数,一个共同的特点就是:都是调用init()进行创建的 public Thread() { init(null, null, &quo ...

  6. 分享到twitter,facebook,google,yahoo,linkedined,msn

    编辑器加载中... 1. 分享到twitter的代码” title=”分享到 Twitter” target=”_blank” rel=”nofollow”>Twitter 2. 分享到Face ...

  7. Swift学习笔记(11)--类与结构体

    类与结构是编程人员在代码中会经常用到的代码块.在类与结构中可以像定义常量,变量和函数一样,定义相关的属性和方法以此来实现各种功能. 和其它的编程语言不太相同的是,Swift不需要单独创建接口或者实现文 ...

  8. 洛谷 P2558 [AHOI2002]网络传输

    P2558 [AHOI2002]网络传输 题目描述 在计算机网络中所有数据都是以二进制形式来传输的. 但是在进行较大数据的传输时,直接使用该数的二进制形式加以传输则往往传输的位数过多. 譬如要传输 1 ...

  9. 深度学习2015年文章整理(CVPR2015)

    国内外从事计算机视觉和图像处理相关领域的著名学者都以在三大顶级会议(ICCV.CVPR和ECCV)上发表论文为荣,其影响力远胜于一般SCI期刊论文.这三大顶级学术会议论文也引领着未来的研究趋势.CVP ...

  10. hadoop集群环境配置成功与否查看方法

    1.Hadoop启动jobhistoryserver来实现web查看作业的历史运行情况,由于在启动hdfs和Yarn进程之后,jobhistoryserver进程并没有启动,需要手动启动jobhist ...