加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Java > 正文

jodd-cache集锦

发布时间:2020-12-14 06:20:50 所属栏目:Java 来源:网络整理
导读:Jodd cache提供了一组cache的实现,其层次如下: 其中, AbstractCacheMap是一个具有计时和大小的缓存map的默认实现,它的实现类必须: 创建一个新的缓存map。 实现自己的删除(prune)策略。 内部使用ReentranReadWriteLock来同步。因为从一个读锁升级到一个

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

其中,

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

  创建一个新的缓存map。

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

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

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

FIFOCache( cacheSize,.cacheSize =.timeout == LinkedHashMap>(cacheSize + 1,1.0f,</span><span style="color: #008000;"&gt;//</span><span style="color: #008000;"&gt; ---------------------------------------------------------------- prune</span> <span style="color: #008000;"&gt;/**</span><span style="color: #008000;"&gt; * Prune expired objects and,if cache is still full,the first one. </span><span style="color: #008000;"&gt;*/</span><span style="color: #000000;"&gt; @Override </span><span style="color: #0000ff;"&gt;protected</span> <span style="color: #0000ff;"&gt;int</span><span style="color: #000000;"&gt; pruneCache() { </span><span style="color: #0000ff;"&gt;int</span> count = 0<span style="color: #000000;"&gt;; CacheObject</span><K,V> first = <span style="color: #0000ff;"&gt;null</span><span style="color: #000000;"&gt;; Iterator</span><CacheObject<K,V>> values =<span style="color: #000000;"&gt; cacheMap.values().iterator(); </span><span style="color: #0000ff;"&gt;while</span><span style="color: #000000;"&gt; (values.hasNext()) { CacheObject</span><K,V> co =<span style="color: #000000;"&gt; values.next(); </span><span style="color: #0000ff;"&gt;if</span> (co.isExpired() == <span style="color: #0000ff;"&gt;true</span><span style="color: #000000;"&gt;) { values.remove(); count</span>++<span style="color: #000000;"&gt;; } </span><span style="color: #0000ff;"&gt;if</span> (first == <span style="color: #0000ff;"&gt;null</span><span style="color: #000000;"&gt;) { first </span>=<span style="color: #000000;"&gt; co; } } </span><span style="color: #0000ff;"&gt;if</span><span style="color: #000000;"&gt; (isFull()) { </span><span style="color: #0000ff;"&gt;if</span> (first != <span style="color: #0000ff;"&gt;null</span><span style="color: #000000;"&gt;) { cacheMap.remove(first.key); count</span>++<span style="color: #000000;"&gt;; } } </span><span style="color: #0000ff;"&gt;return</span><span style="color: #000000;"&gt; count; }</span></pre>

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

LFUCache( maxSize,.cacheSize =.timeout == HashMap>(maxSize + 1</span><span style="color: #008000;"&gt;//</span><span style="color: #008000;"&gt; ---------------------------------------------------------------- prune</span> <span style="color: #008000;"&gt;/**</span><span style="color: #008000;"&gt; * 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;"&gt;*/</span><span style="color: #000000;"&gt; @Override </span><span style="color: #0000ff;"&gt;protected</span> <span style="color: #0000ff;"&gt;int</span><span style="color: #000000;"&gt; pruneCache() { </span><span style="color: #0000ff;"&gt;int</span> count = 0<span style="color: #000000;"&gt;; CacheObject</span><K,V> comin = <span style="color: #0000ff;"&gt;null</span><span style="color: #000000;"&gt;; </span><span style="color: #008000;"&gt;//</span><span style="color: #008000;"&gt; remove expired items and find cached object with minimal access count</span> Iterator<CacheObject<K,V> co =<span style="color: #000000;"&gt; values.next(); </span><span style="color: #0000ff;"&gt;if</span> (co.isExpired() == <span style="color: #0000ff;"&gt;true</span><span style="color: #000000;"&gt;) { values.remove(); onRemove(co.key,co.cachedObject); count</span>++<span style="color: #000000;"&gt;; </span><span style="color: #0000ff;"&gt;continue</span><span style="color: #000000;"&gt;; } </span><span style="color: #0000ff;"&gt;if</span> (comin == <span style="color: #0000ff;"&gt;null</span><span style="color: #000000;"&gt;) { comin </span>=<span style="color: #000000;"&gt; co; } </span><span style="color: #0000ff;"&gt;else</span><span style="color: #000000;"&gt; { </span><span style="color: #0000ff;"&gt;if</span> (co.accessCount <<span style="color: #000000;"&gt; comin.accessCount) { comin </span>=<span style="color: #000000;"&gt; co; } } } </span><span style="color: #0000ff;"&gt;if</span> (isFull() == <span style="color: #0000ff;"&gt;false</span><span style="color: #000000;"&gt;) { </span><span style="color: #0000ff;"&gt;return</span><span style="color: #000000;"&gt; count; } </span><span style="color: #008000;"&gt;//</span><span style="color: #008000;"&gt; decrease access count to all cached objects</span> <span style="color: #0000ff;"&gt;if</span> (comin != <span style="color: #0000ff;"&gt;null</span><span style="color: #000000;"&gt;) { </span><span style="color: #0000ff;"&gt;long</span> minAccessCount =<span style="color: #000000;"&gt; comin.accessCount; values </span>=<span style="color: #000000;"&gt; cacheMap.values().iterator(); </span><span style="color: #0000ff;"&gt;while</span><span style="color: #000000;"&gt; (values.hasNext()) { CacheObject</span><K,V> co =<span style="color: #000000;"&gt; values.next(); co.accessCount </span>-=<span style="color: #000000;"&gt; minAccessCount; </span><span style="color: #0000ff;"&gt;if</span> (co.accessCount <= 0<span style="color: #000000;"&gt;) { values.remove(); onRemove(co.key,co.cachedObject); count</span>++<span style="color: #000000;"&gt;; } } } </span><span style="color: #0000ff;"&gt;return</span><span style="color: #000000;"&gt; count; }</span></pre>

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

LRUCache( cacheSize, LRUCache.</span><span style="color: #008000;"&gt;/**</span><span style="color: #008000;"&gt; * Removes the eldest entry if current cache size exceed cache size. </span><span style="color: #008000;"&gt;*/</span> <span style="color: #0000ff;"&gt;protected</span> <span style="color: #0000ff;"&gt;boolean</span> removeEldestEntry(<span style="color: #0000ff;"&gt;int</span><span style="color: #000000;"&gt; currentSize) { </span><span style="color: #0000ff;"&gt;if</span> (cacheSize == 0<span style="color: #000000;"&gt;) { </span><span style="color: #0000ff;"&gt;return</span> <span style="color: #0000ff;"&gt;false</span><span style="color: #000000;"&gt;; } </span><span style="color: #0000ff;"&gt;return</span> currentSize ><span style="color: #000000;"&gt; cacheSize; } </span><span style="color: #008000;"&gt;//</span><span style="color: #008000;"&gt; ---------------------------------------------------------------- prune</span> <span style="color: #008000;"&gt;/**</span><span style="color: #008000;"&gt; * Prune only expired objects,<code>LinkedHashMap</code> will take care of LRU if needed. </span><span style="color: #008000;"&gt;*/</span><span style="color: #000000;"&gt; @Override </span><span style="color: #0000ff;"&gt;protected</span> <span style="color: #0000ff;"&gt;int</span><span style="color: #000000;"&gt; pruneCache() { </span><span style="color: #0000ff;"&gt;if</span> (isPruneExpiredActive() == <span style="color: #0000ff;"&gt;false</span><span style="color: #000000;"&gt;) { </span><span style="color: #0000ff;"&gt;return</span> 0<span style="color: #000000;"&gt;; } </span><span style="color: #0000ff;"&gt;int</span> count = 0<span style="color: #000000;"&gt;; Iterator</span><CacheObject<K,V> co =<span style="color: #000000;"&gt; values.next(); </span><span style="color: #0000ff;"&gt;if</span> (co.isExpired() == <span style="color: #0000ff;"&gt;true</span><span style="color: #000000;"&gt;) { values.remove(); count</span>++<span style="color: #000000;"&gt;; } } </span><span style="color: #0000ff;"&gt;return</span><span style="color: #000000;"&gt; count; }</span></pre>

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

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

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

LFUCache[]> </span><span style="color: #0000ff;"&gt;protected</span> <span style="color: #0000ff;"&gt;int</span><span style="color: #000000;"&gt; usedSize; </span><span style="color: #008000;"&gt;/**</span><span style="color: #008000;"&gt; * Creates file LFU cache with specified size. Sets * {</span><span style="color: #808080;"&gt;@link</span><span style="color: #008000;"&gt; #maxFileSize max available file size} to half of this value. </span><span style="color: #008000;"&gt;*/</span> <span style="color: #0000ff;"&gt;public</span> FileLFUCache(<span style="color: #0000ff;"&gt;int</span><span style="color: #000000;"&gt; maxSize) { </span><span style="color: #0000ff;"&gt;this</span>(maxSize,maxSize / 2,0<span style="color: #000000;"&gt;); } </span><span style="color: #0000ff;"&gt;public</span> FileLFUCache(<span style="color: #0000ff;"&gt;int</span> maxSize,<span style="color: #0000ff;"&gt;int</span><span style="color: #000000;"&gt; maxFileSize) { </span><span style="color: #0000ff;"&gt;this</span>(maxSize,maxFileSize,0<span style="color: #000000;"&gt;); } </span><span style="color: #008000;"&gt;/**</span><span style="color: #008000;"&gt; * Creates new File LFU cache. * </span><span style="color: #808080;"&gt;@param</span><span style="color: #008000;"&gt; maxSize total cache size in bytes * </span><span style="color: #808080;"&gt;@param</span><span style="color: #008000;"&gt; maxFileSize max available file size in bytes,may be 0 * </span><span style="color: #808080;"&gt;@param</span><span style="color: #008000;"&gt; timeout timeout,may be 0 </span><span style="color: #008000;"&gt;*/</span> <span style="color: #0000ff;"&gt;public</span> FileLFUCache(<span style="color: #0000ff;"&gt;int</span> maxSize,<span style="color: #0000ff;"&gt;int</span> maxFileSize,<span style="color: #0000ff;"&gt;long</span><span style="color: #000000;"&gt; timeout) { </span><span style="color: #0000ff;"&gt;this</span>.cache = <span style="color: #0000ff;"&gt;new</span> LFUCache<File,<span style="color: #0000ff;"&gt;byte</span>[]>(0<span style="color: #000000;"&gt;,timeout) { @Override </span><span style="color: #0000ff;"&gt;public</span> <span style="color: #0000ff;"&gt;boolean</span><span style="color: #000000;"&gt; isFull() { </span><span style="color: #0000ff;"&gt;return</span> usedSize > FileLFUCache.<span style="color: #0000ff;"&gt;this</span><span style="color: #000000;"&gt;.maxSize; } @Override </span><span style="color: #0000ff;"&gt;protected</span> <span style="color: #0000ff;"&gt;void</span> onRemove(File key,<span style="color: #0000ff;"&gt;byte</span><span style="color: #000000;"&gt;[] cachedObject) { usedSize </span>-=<span style="color: #000000;"&gt; cachedObject.length; } }; </span><span style="color: #0000ff;"&gt;this</span>.maxSize =<span style="color: #000000;"&gt; maxSize; </span><span style="color: #0000ff;"&gt;this</span>.maxFileSize =<span style="color: #000000;"&gt; maxFileSize; } </span><span style="color: #008000;"&gt;//</span><span style="color: #008000;"&gt; ---------------------------------------------------------------- get</span> <span style="color: #008000;"&gt;/**</span><span style="color: #008000;"&gt; * Returns max cache size in bytes. </span><span style="color: #008000;"&gt;*/</span> <span style="color: #0000ff;"&gt;public</span> <span style="color: #0000ff;"&gt;int</span><span style="color: #000000;"&gt; getMaxSize() { </span><span style="color: #0000ff;"&gt;return</span><span style="color: #000000;"&gt; maxSize; } </span><span style="color: #008000;"&gt;/**</span><span style="color: #008000;"&gt; * Returns actually used size in bytes. </span><span style="color: #008000;"&gt;*/</span> <span style="color: #0000ff;"&gt;public</span> <span style="color: #0000ff;"&gt;int</span><span style="color: #000000;"&gt; getUsedSize() { </span><span style="color: #0000ff;"&gt;return</span><span style="color: #000000;"&gt; usedSize; } </span><span style="color: #008000;"&gt;/**</span><span style="color: #008000;"&gt; * 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;"&gt;*/</span> <span style="color: #0000ff;"&gt;public</span> <span style="color: #0000ff;"&gt;int</span><span style="color: #000000;"&gt; getMaxFileSize() { </span><span style="color: #0000ff;"&gt;return</span><span style="color: #000000;"&gt; maxFileSize; } </span><span style="color: #008000;"&gt;/**</span><span style="color: #008000;"&gt; * Returns number of cached files. </span><span style="color: #008000;"&gt;*/</span> <span style="color: #0000ff;"&gt;public</span> <span style="color: #0000ff;"&gt;int</span><span style="color: #000000;"&gt; getCachedFilesCount() { </span><span style="color: #0000ff;"&gt;return</span><span style="color: #000000;"&gt; cache.size(); } </span><span style="color: #008000;"&gt;/**</span><span style="color: #008000;"&gt; * Returns timeout. </span><span style="color: #008000;"&gt;*/</span> <span style="color: #0000ff;"&gt;public</span> <span style="color: #0000ff;"&gt;long</span><span style="color: #000000;"&gt; getCacheTimeout() { </span><span style="color: #0000ff;"&gt;return</span><span style="color: #000000;"&gt; cache.getCacheTimeout(); } </span><span style="color: #008000;"&gt;/**</span><span style="color: #008000;"&gt; * Clears the cache. </span><span style="color: #008000;"&gt;*/</span> <span style="color: #0000ff;"&gt;public</span> <span style="color: #0000ff;"&gt;void</span><span style="color: #000000;"&gt; clear() { cache.clear(); usedSize </span>= 0<span style="color: #000000;"&gt;; } </span><span style="color: #008000;"&gt;//</span><span style="color: #008000;"&gt; ---------------------------------------------------------------- get</span> <span style="color: #0000ff;"&gt;public</span> <span style="color: #0000ff;"&gt;byte</span>[] getFileBytes(String fileName) <span style="color: #0000ff;"&gt;throws</span><span style="color: #000000;"&gt; IOException { </span><span style="color: #0000ff;"&gt;return</span> getFileBytes(<span style="color: #0000ff;"&gt;new</span><span style="color: #000000;"&gt; File(fileName)); } </span><span style="color: #008000;"&gt;/**</span><span style="color: #008000;"&gt; * Returns cached file bytes. </span><span style="color: #008000;"&gt;*/</span> <span style="color: #0000ff;"&gt;public</span> <span style="color: #0000ff;"&gt;byte</span>[] getFileBytes(File file) <span style="color: #0000ff;"&gt;throws</span><span style="color: #000000;"&gt; IOException { </span><span style="color: #0000ff;"&gt;byte</span>[] bytes =<span style="color: #000000;"&gt; cache.get(file); </span><span style="color: #0000ff;"&gt;if</span> (bytes != <span style="color: #0000ff;"&gt;null</span><span style="color: #000000;"&gt;) { </span><span style="color: #0000ff;"&gt;return</span><span style="color: #000000;"&gt; bytes; } </span><span style="color: #008000;"&gt;//</span><span style="color: #008000;"&gt; add file</span> bytes =<span style="color: #000000;"&gt; FileUtil.readBytes(file); </span><span style="color: #0000ff;"&gt;if</span> ((maxFileSize != 0) &amp;&amp; (file.length() ><span style="color: #000000;"&gt; maxFileSize)) { </span><span style="color: #008000;"&gt;//</span><span style="color: #008000;"&gt; don't cache files that size exceed max allowed file size</span> <span style="color: #0000ff;"&gt;return</span><span style="color: #000000;"&gt; bytes; } usedSize </span>+=<span style="color: #000000;"&gt; bytes.length; </span><span style="color: #008000;"&gt;//</span><span style="color: #008000;"&gt; put file into cache </span><span style="color: #008000;"&gt;//</span><span style="color: #008000;"&gt; if used size > total,purge() will be invoked</span>

<span style="color: #000000;"> cache.put(file,bytes);

    </span><span style="color: #0000ff;"&gt;return</span><span style="color: #000000;"&gt; bytes;
}</span></pre>

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读