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 + -
显示快捷键?