📄 utilcache.java
字号:
/*
* $Id: UtilCache.java,v 1.2 2004/02/26 16:22:09 jonesde Exp $
*
* Copyright (c) 2001-2004 The Open For Business Project - www.ofbiz.org
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT
* OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
* THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package org.ofbiz.base.util;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Map;
import java.util.ResourceBundle;
/**
* Generalized caching utility. Provides a number of caching features:
* <ul>
* <li>Limited or unlimited element capacity
* <li>If limited, removes elements with the LRU (Least Recently Used) algorithm
* <li>Keeps track of when each element was loaded into the cache
* <li>Using the expireTime can report whether a given element has expired
* <li>Counts misses and hits
* </ul>
*
* @author <a href="mailto:jonesde@ofbiz.org">David E. Jones</a>
* @version $Revision: 1.2 $
* @since 2.0
*/
public class UtilCache {
/** A static Map to keep track of all of the UtilCache instances. */
public static Map utilCacheTable = new HashMap();
/** An index number appended to utilCacheTable names when there are conflicts. */
protected static Map defaultIndices = new HashMap();
/** The name of the UtilCache instance, is also the key for the instance in utilCacheTable. */
protected String name;
/** A list of the elements order by Least Recent Use */
public LinkedList keyLRUList = new LinkedList();
/** A hashtable containing a CacheLine object with a value and a loadTime for each element. */
public Map cacheLineTable = new HashMap();
/** A count of the number of cache hits */
protected long hitCount = 0;
/** A count of the number of cache misses */
protected long missCount = 0;
/** The maximum number of elements in the cache.
* If set to 0, there will be no limit on the number of elements in the cache.
*/
protected long maxSize = 0;
/** Specifies the amount of time since initial loading before an element will be reported as expired.
* If set to 0, elements will never expire.
*/
protected long expireTime = 0;
/** Specifies whether or not to use soft references for this cache, defaults to false */
protected boolean useSoftReference = false;
/** Constructor which specifies the cacheName as well as the maxSize, expireTime and useSoftReference.
* The passed maxSize, expireTime and useSoftReference will be overridden by values from cache.properties if found.
* @param maxSize The maxSize member is set to this value
* @param expireTime The expireTime member is set to this value
* @param cacheName The name of the cache.
* @param useSoftReference Specifies whether or not to use soft references for this cache.
*/
public UtilCache(String cacheName, long maxSize, long expireTime, boolean useSoftReference) {
this.useSoftReference = useSoftReference;
this.maxSize = maxSize;
this.expireTime = expireTime;
setPropertiesParams(cacheName);
name = cacheName + this.getNextDefaultIndex(cacheName);
utilCacheTable.put(name, this);
}
/** Constructor which specifies the cacheName as well as the maxSize and expireTime.
* The passed maxSize and expireTime will be overridden by values from cache.properties if found.
* @param maxSize The maxSize member is set to this value
* @param expireTime The expireTime member is set to this value
* @param cacheName The name of the cache.
*/
public UtilCache(String cacheName, long maxSize, long expireTime) {
this(cacheName, maxSize, expireTime, false);
}
/** Constructor which specifies the maxSize and expireTime.
* @param maxSize The maxSize member is set to this value
* @param expireTime The expireTime member is set to this value
*/
public UtilCache(long maxSize, long expireTime) {
this.useSoftReference = false;
this.maxSize = maxSize;
this.expireTime = expireTime;
String name = "specified" + this.getNextDefaultIndex("specified");
setPropertiesParams(name);
utilCacheTable.put(name, this);
}
/** This constructor takes a name for the cache, puts itself in the utilCacheTable.
* It also uses the cacheName to lookup the initialization parameters from cache.properties.
* @param cacheName The name of the cache.
*/
public UtilCache(String cacheName) {
setPropertiesParams("default");
setPropertiesParams(cacheName);
name = cacheName + this.getNextDefaultIndex(cacheName);
utilCacheTable.put(name, this);
}
/** Default constructor, all members stay at default values as defined in cache.properties, or the defaults in this file if cache.properties is not found, or there are no 'default' entries in it. */
public UtilCache() {
setPropertiesParams("default");
name = "default" + this.getNextDefaultIndex("default");
utilCacheTable.put(name, this);
}
protected String getNextDefaultIndex(String cacheName) {
Integer curInd = (Integer) UtilCache.defaultIndices.get(cacheName);
if (curInd == null) {
UtilCache.defaultIndices.put(cacheName, new Integer(1));
return "";
} else {
UtilCache.defaultIndices.put(cacheName, new Integer(curInd.intValue() + 1));
return Integer.toString(curInd.intValue() + 1);
}
}
protected void setPropertiesParams(String cacheName) {
ResourceBundle res = ResourceBundle.getBundle("cache");
if (res != null) {
try {
String value = res.getString(cacheName + ".maxSize");
Long longValue = new Long(value);
if (longValue != null) {
maxSize = longValue.longValue();
}
} catch (Exception e) {}
try {
String value = res.getString(cacheName + ".expireTime");
Long longValue = new Long(value);
if (longValue != null) {
expireTime = longValue.longValue();
}
} catch (Exception e) {}
try {
String value = res.getString(cacheName + ".useSoftReference");
if (value != null) {
useSoftReference = "true".equals(value);
}
} catch (Exception e) {}
}
}
/** Puts or loads the passed element into the cache
* @param key The key for the element, used to reference it in the hastables and LRU linked list
* @param value The value of the element
*/
public synchronized void put(Object key, Object value) {
if (key == null)
return;
if (maxSize > 0) {
// when maxSize is changed, the setter will take care of filling the LRU list
if (cacheLineTable.containsKey(key)) {
keyLRUList.remove(key);
keyLRUList.addFirst(key);
} else {
keyLRUList.addFirst(key);
}
}
if (expireTime > 0) {
cacheLineTable.put(key, new UtilCache.CacheLine(value, useSoftReference, System.currentTimeMillis()));
} else {
cacheLineTable.put(key, new UtilCache.CacheLine(value, useSoftReference));
}
if (maxSize > 0 && cacheLineTable.size() > maxSize) {
Object lastKey = keyLRUList.getLast();
remove(lastKey);
}
}
/** Gets an element from the cache according to the specified key.
* If the requested element hasExpired, it is removed before it is looked up which causes the function to return null.
* @param key The key for the element, used to reference it in the hastables and LRU linked list
* @return The value of the element specified by the key
*/
public Object get(Object key) {
if (key == null) {
missCount++;
return null;
}
UtilCache.CacheLine line = (UtilCache.CacheLine) cacheLineTable.get(key);
if (hasExpired(line)) {
// note that print.info in debug.properties cannot be checked through UtilProperties here, it would cause infinite recursion...
// if (Debug.infoOn()) Debug.logInfo("Element has expired with key " + key, module);
remove(key);
line = null;
}
if (line == null) {
// if (Debug.infoOn()) Debug.logInfo("Element not found with key " + key, module);
missCount++;
return null;
}
// if (Debug.infoOn()) Debug.logInfo("Element found with key " + key, module);
hitCount++;
if (maxSize > 0) {
synchronized (this) {
keyLRUList.remove(key);
keyLRUList.addFirst(key);
}
}
return line.getValue();
}
/** Removes an element from the cache according to the specified key
* @param key The key for the element, used to reference it in the hastables and LRU linked list
* @return The value of the removed element specified by the key
*/
public synchronized Object remove(Object key) {
if (key == null) {
missCount++;
return null;
}
UtilCache.CacheLine line = (UtilCache.CacheLine) cacheLineTable.remove(key);
if (line != null) {
if (maxSize > 0) keyLRUList.remove(key);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -