jodd-cache集锦
Jodd cache提供了一组cache的实现,其层次如下: 其中, AbstractCacheMap是一个具有计时和大小的缓存map的默认实现,它的实现类必须: 创建一个新的缓存map。 实现自己的删除(prune)策略。 内部使用ReentranReadWriteLock来同步。因为从一个读锁升级到一个写锁是不可能的,因此在get(Object)方法内要注意。 FIFOCach:先进先出缓存。优点是简单高效。缺点是不灵活,没有在内存中保存常用的缓存对象。
FIFOCache( cacheSize,.cacheSize =.timeout == LinkedHashMap
</span><span style="color: #008000;">//</span><span style="color: #008000;"> ---------------------------------------------------------------- prune</span>
<span style="color: #008000;">/**</span><span style="color: #008000;">
* Prune expired objects and,if cache is still full,the first one.
</span><span style="color: #008000;">*/</span><span style="color: #000000;">
@Override
</span><span style="color: #0000ff;">protected</span> <span style="color: #0000ff;">int</span><span style="color: #000000;"> pruneCache() {
</span><span style="color: #0000ff;">int</span> count = 0<span style="color: #000000;">;
CacheObject</span><K,V> first = <span style="color: #0000ff;">null</span><span style="color: #000000;">;
Iterator</span><CacheObject<K,V>> values =<span style="color: #000000;"> cacheMap.values().iterator();
</span><span style="color: #0000ff;">while</span><span style="color: #000000;"> (values.hasNext()) {
CacheObject</span><K,V> co =<span style="color: #000000;"> values.next();
</span><span style="color: #0000ff;">if</span> (co.isExpired() == <span style="color: #0000ff;">true</span><span style="color: #000000;">) {
values.remove();
count</span>++<span style="color: #000000;">;
}
</span><span style="color: #0000ff;">if</span> (first == <span style="color: #0000ff;">null</span><span style="color: #000000;">) {
first </span>=<span style="color: #000000;"> co;
}
}
</span><span style="color: #0000ff;">if</span><span style="color: #000000;"> (isFull()) {
</span><span style="color: #0000ff;">if</span> (first != <span style="color: #0000ff;">null</span><span style="color: #000000;">) {
cacheMap.remove(first.key);
count</span>++<span style="color: #000000;">;
}
}
</span><span style="color: #0000ff;">return</span><span style="color: #000000;"> count;
}</span></pre>
LFUCache:最少访问次数缓存。优点是常用缓存保留在内存中,偶然会使扫描算法失效。缺点是大的获取消耗即这个算法不能快速适应变化的使用模式,特别是集群的临时获取是无效的。 LFUCache( maxSize,.cacheSize =.timeout == HashMap
</span><span style="color: #008000;">//</span><span style="color: #008000;"> ---------------------------------------------------------------- prune</span>
<span style="color: #008000;">/**</span><span style="color: #008000;">
* Prunes expired and,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.
</span><span style="color: #008000;">*/</span><span style="color: #000000;">
@Override
</span><span style="color: #0000ff;">protected</span> <span style="color: #0000ff;">int</span><span style="color: #000000;"> pruneCache() {
</span><span style="color: #0000ff;">int</span> count = 0<span style="color: #000000;">;
CacheObject</span><K,V> comin = <span style="color: #0000ff;">null</span><span style="color: #000000;">;
</span><span style="color: #008000;">//</span><span style="color: #008000;"> remove expired items and find cached object with minimal access count</span>
Iterator<CacheObject<K,V> co =<span style="color: #000000;"> values.next();
</span><span style="color: #0000ff;">if</span> (co.isExpired() == <span style="color: #0000ff;">true</span><span style="color: #000000;">) {
values.remove();
onRemove(co.key,co.cachedObject);
count</span>++<span style="color: #000000;">;
</span><span style="color: #0000ff;">continue</span><span style="color: #000000;">;
}
</span><span style="color: #0000ff;">if</span> (comin == <span style="color: #0000ff;">null</span><span style="color: #000000;">) {
comin </span>=<span style="color: #000000;"> co;
} </span><span style="color: #0000ff;">else</span><span style="color: #000000;"> {
</span><span style="color: #0000ff;">if</span> (co.accessCount <<span style="color: #000000;"> comin.accessCount) {
comin </span>=<span style="color: #000000;"> co;
}
}
}
</span><span style="color: #0000ff;">if</span> (isFull() == <span style="color: #0000ff;">false</span><span style="color: #000000;">) {
</span><span style="color: #0000ff;">return</span><span style="color: #000000;"> count;
}
</span><span style="color: #008000;">//</span><span style="color: #008000;"> decrease access count to all cached objects</span>
<span style="color: #0000ff;">if</span> (comin != <span style="color: #0000ff;">null</span><span style="color: #000000;">) {
</span><span style="color: #0000ff;">long</span> minAccessCount =<span style="color: #000000;"> comin.accessCount;
values </span>=<span style="color: #000000;"> cacheMap.values().iterator();
</span><span style="color: #0000ff;">while</span><span style="color: #000000;"> (values.hasNext()) {
CacheObject</span><K,V> co =<span style="color: #000000;"> values.next();
co.accessCount </span>-=<span style="color: #000000;"> minAccessCount;
</span><span style="color: #0000ff;">if</span> (co.accessCount <= 0<span style="color: #000000;">) {
values.remove();
onRemove(co.key,co.cachedObject);
count</span>++<span style="color: #000000;">;
}
}
}
</span><span style="color: #0000ff;">return</span><span style="color: #000000;"> count;
}</span></pre>
LRUCache:最近未访问缓存。缓存对象的消耗是一个常量。简单高效,比FIFO更适应一个变化的场景。缺点是可能会被不会重新访问的缓存占满空间,特别是在面对获取类型扫描时则完全不起作用。然后它是目前最常用的缓存算法。
LRUCache( cacheSize, LRUCache.
</span><span style="color: #008000;">/**</span><span style="color: #008000;">
* Removes the eldest entry if current cache size exceed cache size.
</span><span style="color: #008000;">*/</span>
<span style="color: #0000ff;">protected</span> <span style="color: #0000ff;">boolean</span> removeEldestEntry(<span style="color: #0000ff;">int</span><span style="color: #000000;"> currentSize) {
</span><span style="color: #0000ff;">if</span> (cacheSize == 0<span style="color: #000000;">) {
</span><span style="color: #0000ff;">return</span> <span style="color: #0000ff;">false</span><span style="color: #000000;">;
}
</span><span style="color: #0000ff;">return</span> currentSize ><span style="color: #000000;"> cacheSize;
}
</span><span style="color: #008000;">//</span><span style="color: #008000;"> ---------------------------------------------------------------- prune</span>
<span style="color: #008000;">/**</span><span style="color: #008000;">
* Prune only expired objects,<code>LinkedHashMap</code> will take care of LRU if needed.
</span><span style="color: #008000;">*/</span><span style="color: #000000;">
@Override
</span><span style="color: #0000ff;">protected</span> <span style="color: #0000ff;">int</span><span style="color: #000000;"> pruneCache() {
</span><span style="color: #0000ff;">if</span> (isPruneExpiredActive() == <span style="color: #0000ff;">false</span><span style="color: #000000;">) {
</span><span style="color: #0000ff;">return</span> 0<span style="color: #000000;">;
}
</span><span style="color: #0000ff;">int</span> count = 0<span style="color: #000000;">;
Iterator</span><CacheObject<K,V> co =<span style="color: #000000;"> values.next();
</span><span style="color: #0000ff;">if</span> (co.isExpired() == <span style="color: #0000ff;">true</span><span style="color: #000000;">) {
values.remove();
count</span>++<span style="color: #000000;">;
}
}
</span><span style="color: #0000ff;">return</span><span style="color: #000000;"> count;
}</span></pre>
TimedCache 不限制大小,只有当对象过期时才会删除。标准的chache方法不会显式的调用删除(prune),而是根据定义好的延迟进行定时删除。 TimedCache(.cacheSize = 0.timeout == HashMap
</span><span style="color: #008000;">//</span><span style="color: #008000;"> ---------------------------------------------------------------- prune</span>
<span style="color: #008000;">/**</span><span style="color: #008000;">
* Prunes expired elements from the cache. Returns the number of removed objects.
</span><span style="color: #008000;">*/</span><span style="color: #000000;">
@Override
</span><span style="color: #0000ff;">protected</span> <span style="color: #0000ff;">int</span><span style="color: #000000;"> pruneCache() {
</span><span style="color: #0000ff;">int</span> count = 0<span style="color: #000000;">;
Iterator</span><CacheObject<K,V>> values =<span style="color: #000000;"> cacheMap.values().iterator();
</span><span style="color: #0000ff;">while</span><span style="color: #000000;"> (values.hasNext()) {
CacheObject co </span>=<span style="color: #000000;"> values.next();
</span><span style="color: #0000ff;">if</span> (co.isExpired() == <span style="color: #0000ff;">true</span><span style="color: #000000;">) {
values.remove();
count</span>++<span style="color: #000000;">;
}
}
</span><span style="color: #0000ff;">return</span><span style="color: #000000;"> count;
}
</span><span style="color: #008000;">//</span><span style="color: #008000;"> ---------------------------------------------------------------- auto prune</span>
<span style="color: #0000ff;">protected</span><span style="color: #000000;"> Timer pruneTimer;
</span><span style="color: #008000;">/**</span><span style="color: #008000;">
* Schedules prune.
</span><span style="color: #008000;">*/</span>
<span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span> schedulePrune(<span style="color: #0000ff;">long</span><span style="color: #000000;"> delay) {
</span><span style="color: #0000ff;">if</span> (pruneTimer != <span style="color: #0000ff;">null</span><span style="color: #000000;">) {
pruneTimer.cancel();
}
pruneTimer </span>= <span style="color: #0000ff;">new</span><span style="color: #000000;"> Timer();
pruneTimer.schedule(
</span><span style="color: #0000ff;">new</span><span style="color: #000000;"> TimerTask() {
@Override
</span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> run() {
prune();
}
},delay,delay
);
}
</span><span style="color: #008000;">/**</span><span style="color: #008000;">
* Cancels prune schedules.
</span><span style="color: #008000;">*/</span>
<span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> cancelPruneSchedule() {
</span><span style="color: #0000ff;">if</span> (pruneTimer != <span style="color: #0000ff;">null</span><span style="color: #000000;">) {
pruneTimer.cancel();
pruneTimer </span>= <span style="color: #0000ff;">null</span><span style="color: #000000;">;
}
}</span></pre>
注意,还提供了一个FileLFUCache,没有继承AbstractCacheMap.用LFU将文件缓存到内存,极大加快访问常用文件的性能。 LFUCache </span><span style="color: #0000ff;">protected</span> <span style="color: #0000ff;">int</span><span style="color: #000000;"> usedSize;
</span><span style="color: #008000;">/**</span><span style="color: #008000;">
* Creates file LFU cache with specified size. Sets
* {</span><span style="color: #808080;">@link</span><span style="color: #008000;"> #maxFileSize max available file size} to half of this value.
</span><span style="color: #008000;">*/</span>
<span style="color: #0000ff;">public</span> FileLFUCache(<span style="color: #0000ff;">int</span><span style="color: #000000;"> maxSize) {
</span><span style="color: #0000ff;">this</span>(maxSize,maxSize / 2,0<span style="color: #000000;">);
}
</span><span style="color: #0000ff;">public</span> FileLFUCache(<span style="color: #0000ff;">int</span> maxSize,<span style="color: #0000ff;">int</span><span style="color: #000000;"> maxFileSize) {
</span><span style="color: #0000ff;">this</span>(maxSize,maxFileSize,0<span style="color: #000000;">);
}
</span><span style="color: #008000;">/**</span><span style="color: #008000;">
* Creates new File LFU cache.
* </span><span style="color: #808080;">@param</span><span style="color: #008000;"> maxSize total cache size in bytes
* </span><span style="color: #808080;">@param</span><span style="color: #008000;"> maxFileSize max available file size in bytes,may be 0
* </span><span style="color: #808080;">@param</span><span style="color: #008000;"> timeout timeout,may be 0
</span><span style="color: #008000;">*/</span>
<span style="color: #0000ff;">public</span> FileLFUCache(<span style="color: #0000ff;">int</span> maxSize,<span style="color: #0000ff;">int</span> maxFileSize,<span style="color: #0000ff;">long</span><span style="color: #000000;"> timeout) {
</span><span style="color: #0000ff;">this</span>.cache = <span style="color: #0000ff;">new</span> LFUCache<File,<span style="color: #0000ff;">byte</span>[]>(0<span style="color: #000000;">,timeout) {
@Override
</span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">boolean</span><span style="color: #000000;"> isFull() {
</span><span style="color: #0000ff;">return</span> usedSize > FileLFUCache.<span style="color: #0000ff;">this</span><span style="color: #000000;">.maxSize;
}
@Override
</span><span style="color: #0000ff;">protected</span> <span style="color: #0000ff;">void</span> onRemove(File key,<span style="color: #0000ff;">byte</span><span style="color: #000000;">[] cachedObject) {
usedSize </span>-=<span style="color: #000000;"> cachedObject.length;
}
};
</span><span style="color: #0000ff;">this</span>.maxSize =<span style="color: #000000;"> maxSize;
</span><span style="color: #0000ff;">this</span>.maxFileSize =<span style="color: #000000;"> maxFileSize;
}
</span><span style="color: #008000;">//</span><span style="color: #008000;"> ---------------------------------------------------------------- get</span>
<span style="color: #008000;">/**</span><span style="color: #008000;">
* Returns max cache size in bytes.
</span><span style="color: #008000;">*/</span>
<span style="color: #0000ff;">public</span> <span style="color: #0000ff;">int</span><span style="color: #000000;"> getMaxSize() {
</span><span style="color: #0000ff;">return</span><span style="color: #000000;"> maxSize;
}
</span><span style="color: #008000;">/**</span><span style="color: #008000;">
* Returns actually used size in bytes.
</span><span style="color: #008000;">*/</span>
<span style="color: #0000ff;">public</span> <span style="color: #0000ff;">int</span><span style="color: #000000;"> getUsedSize() {
</span><span style="color: #0000ff;">return</span><span style="color: #000000;"> usedSize;
}
</span><span style="color: #008000;">/**</span><span style="color: #008000;">
* 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.
</span><span style="color: #008000;">*/</span>
<span style="color: #0000ff;">public</span> <span style="color: #0000ff;">int</span><span style="color: #000000;"> getMaxFileSize() {
</span><span style="color: #0000ff;">return</span><span style="color: #000000;"> maxFileSize;
}
</span><span style="color: #008000;">/**</span><span style="color: #008000;">
* Returns number of cached files.
</span><span style="color: #008000;">*/</span>
<span style="color: #0000ff;">public</span> <span style="color: #0000ff;">int</span><span style="color: #000000;"> getCachedFilesCount() {
</span><span style="color: #0000ff;">return</span><span style="color: #000000;"> cache.size();
}
</span><span style="color: #008000;">/**</span><span style="color: #008000;">
* Returns timeout.
</span><span style="color: #008000;">*/</span>
<span style="color: #0000ff;">public</span> <span style="color: #0000ff;">long</span><span style="color: #000000;"> getCacheTimeout() {
</span><span style="color: #0000ff;">return</span><span style="color: #000000;"> cache.getCacheTimeout();
}
</span><span style="color: #008000;">/**</span><span style="color: #008000;">
* Clears the cache.
</span><span style="color: #008000;">*/</span>
<span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> clear() {
cache.clear();
usedSize </span>= 0<span style="color: #000000;">;
}
</span><span style="color: #008000;">//</span><span style="color: #008000;"> ---------------------------------------------------------------- get</span>
<span style="color: #0000ff;">public</span> <span style="color: #0000ff;">byte</span>[] getFileBytes(String fileName) <span style="color: #0000ff;">throws</span><span style="color: #000000;"> IOException {
</span><span style="color: #0000ff;">return</span> getFileBytes(<span style="color: #0000ff;">new</span><span style="color: #000000;"> File(fileName));
}
</span><span style="color: #008000;">/**</span><span style="color: #008000;">
* Returns cached file bytes.
</span><span style="color: #008000;">*/</span>
<span style="color: #0000ff;">public</span> <span style="color: #0000ff;">byte</span>[] getFileBytes(File file) <span style="color: #0000ff;">throws</span><span style="color: #000000;"> IOException {
</span><span style="color: #0000ff;">byte</span>[] bytes =<span style="color: #000000;"> cache.get(file);
</span><span style="color: #0000ff;">if</span> (bytes != <span style="color: #0000ff;">null</span><span style="color: #000000;">) {
</span><span style="color: #0000ff;">return</span><span style="color: #000000;"> bytes;
}
</span><span style="color: #008000;">//</span><span style="color: #008000;"> add file</span>
bytes =<span style="color: #000000;"> FileUtil.readBytes(file);
</span><span style="color: #0000ff;">if</span> ((maxFileSize != 0) && (file.length() ><span style="color: #000000;"> maxFileSize)) {
</span><span style="color: #008000;">//</span><span style="color: #008000;"> don't cache files that size exceed max allowed file size</span>
<span style="color: #0000ff;">return</span><span style="color: #000000;"> bytes;
}
usedSize </span>+=<span style="color: #000000;"> bytes.length;
</span><span style="color: #008000;">//</span><span style="color: #008000;"> put file into cache
</span><span style="color: #008000;">//</span><span style="color: #008000;"> if used size > total,purge() will be invoked</span>
<span style="color: #000000;"> cache.put(file,bytes);
(编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |