utilcache.java
来自「用jbuilder写的源程序」· Java 代码 · 共 694 行 · 第 1/2 页
JAVA
694 行
/*
* $Id: UtilCache.java,v 1.2 2005/01/31 05:27:54 jdon Exp $
*
* Copyright (c) 2001, 2002 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 com.jdon.util;
import java.text.DecimalFormat;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* <p>
* 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 {
public static String module = UtilCache.class.getName();
// decimal formatter for cache values
static final DecimalFormat percentFormat = new DecimalFormat("#0.0");
private PropsUtil propsUtil;
/** A static Map to keep track of all of the UtilCache instances. */
public static Map utilCacheTable = new ConcurrentHashMap();
/**
* An index number appended to utilCacheTable names when there are
* conflicts.
*/
protected static Map defaultIndices = new ConcurrentHashMap();
/**
* 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.
* for above jdk1.5
*/
public Map cacheLineTable = new ConcurrentHashMap();
/** 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(PropsUtil propsUtil, String cacheName, long maxSize, long expireTime, boolean useSoftReference) {
this.propsUtil = propsUtil;
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(PropsUtil propsUtil, String cacheName, long maxSize, long expireTime) {
this(propsUtil, 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(PropsUtil propsUtil, long maxSize, long expireTime) {
this.propsUtil = propsUtil;
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(PropsUtil propsUtil, String cacheName) {
this.propsUtil = propsUtil;
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(PropsUtil propsUtil) {
this.propsUtil = propsUtil;
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) {
if (propsUtil == null) {
System.err.println(" UtilCache propsUtil not yet set!! ");
return;
}
try {
String value = propsUtil.getProperty("cache." + cacheName + ".maxSize");
if (UtilValidate.isNotEmpty(value)) {
Debug.logVerbose("[JdonFramework]found cache configure: cache." + cacheName + ".maxSize = " + value, module);
Long longValue = new Long(value);
if (longValue != null) {
maxSize = longValue.longValue();
}
}
} catch (Exception e) {
}
try {
String value = propsUtil.getProperty("cache." + cacheName + ".expireTime");
if (UtilValidate.isNotEmpty(value)) {
Long longValue = new Long(value);
if (longValue != null) {
expireTime = longValue.longValue();
}
}
} catch (Exception e) {
}
try {
String value = propsUtil.getProperty("cache." + cacheName + ".useSoftReference");
if (UtilValidate.isNotEmpty(value)) {
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);
}
Debug.logVerbose("[JdonFramework]cache now size = " + keyLRUList.size() + " maxSize =" + maxSize +
" this Cache id:" + this.hashCode(), module);
}
/**
* 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);
remove(key);
line = null;
}
if (line == null) {
// if (Debug.infoOn()) Debug.logInfo("Element not found with key " +
// key);
missCount++;
return null;
}
// if (Debug.infoOn()) Debug.logInfo("Element found with key " + key);
hitCount++;
//double hitPercent = 100*(double)hitCount/(hitCount + missCount);
//Debug.logVerbose("[JdonFramework]cache hit percent: " + percentFormat.format(hitPercent)+"%", module);
if (maxSize > 0) {
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;
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?