⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 softcache.java

📁 Java Crawler with domain knowledge path
💻 JAVA
字号:
/** * JDBM LICENSE v1.00 * * Redistribution and use of this software and associated documentation * ("Software"), with or without modification, are permitted provided * that the following conditions are met: * * 1. Redistributions of source code must retain copyright *    statements and notices.  Redistributions must also contain a *    copy of this document. * * 2. Redistributions in binary form must reproduce the *    above copyright notice, this list of conditions and the *    following disclaimer in the documentation and/or other *    materials provided with the distribution. * * 3. The name "JDBM" must not be used to endorse or promote *    products derived from this Software without prior written *    permission of Cees de Groot.  For written permission, *    please contact cg@cdegroot.com. * * 4. Products derived from this Software may not be called "JDBM" *    nor may "JDBM" appear in their names without prior written *    permission of Cees de Groot. * * 5. Due credit should be given to the JDBM Project *    (http://jdbm.sourceforge.net/). * * THIS SOFTWARE IS PROVIDED BY THE JDBM PROJECT AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL * CEES DE GROOT OR ANY CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. * * Copyright 2000 (C) Cees de Groot. All Rights Reserved. * Contributions are Copyright (C) 2000 by their associated contributors. * * $Id */package jdbm.helper;import java.lang.ref.ReferenceQueue;import java.lang.ref.SoftReference;import java.lang.ref.Reference;import java.util.Enumeration;import java.util.Map;import java.util.HashMap;/** * Wraps a deterministic cache policy with a <q>Level-2</q> cache based on * J2SE's {@link SoftReference soft references}. Soft references allow * this cache to keep references to objects until the memory they occupy * is required elsewhere. * <p> * Since the {@link CachePolicy} interface requires an event be fired * when an object is evicted, and the event contains the actual object, * this class cannot be a stand-alone implementation of * <code>CachePolicy</code>. This limitation arises because Java References * does not support notification before references are cleared; nor do * they support reaching soft referents. Therefore, this wrapper cache * aggressively notifies evictions: events are fired when the objects are * evicted from the internal cache. Consequently, the soft cache may return * a non-null object when <code>get( )</code> is called, even if that * object was said to have been evicted. * <p> * The current implementation uses a hash structure for its internal key * to value mappings. * <p> * Note: this component's publicly exposed methods are not threadsafe; * potentially concurrent code should synchronize on the cache instance. * * @author <a href="mailto:dranatunga@users.sourceforge.net">Dilum Ranatunga</a> * @version $Id: SoftCache.java,v 1.1 2003/11/01 13:29:27 dranatunga Exp $ */public class SoftCache implements CachePolicy {    private static final int INITIAL_CAPACITY = 128;    private static final float DEFAULT_LOAD_FACTOR = 1.5f;    private final ReferenceQueue _clearQueue = new ReferenceQueue();    private final CachePolicy _internal;    private final Map _cacheMap;    /**     * Creates a soft-reference based L2 cache with a {@link MRU} cache as     * the internal (L1) cache. The soft reference cache uses the     * default load capacity of 1.5f, which is intended to sacrifice some     * performance for space. This compromise is reasonable, since all     * {@link #get(Object) get( )s} first try the L1 cache anyway. The     * internal MRU is given a capacity of 128 elements.     */    public SoftCache() {        this(new MRU(INITIAL_CAPACITY));    }    /**     * Creates a soft-reference based L2 cache wrapping the specified     * L1 cache.     *     * @param internal non null internal cache.     * @throws NullPointerException if the internal cache is null.     */    public SoftCache(CachePolicy internal) throws NullPointerException {        this(DEFAULT_LOAD_FACTOR, internal);    }    /**     * Creates a soft-reference based L2 cache wrapping the specified     * L1 cache. This constructor is somewhat implementation-specific,     * so users are encouraged to use {@link #SoftCache(CachePolicy)}     * instead.     *     * @param loadFactor load factor that the soft cache's hash structure     *        should use.     * @param internal non null internal cache.     * @throws IllegalArgumentException if the load factor is nonpositive.     * @throws NullPointerException if the internal cache is null.     */    public SoftCache(float loadFactor, CachePolicy internal) throws IllegalArgumentException, NullPointerException {        if (internal == null) {            throw new NullPointerException("Internal cache cannot be null.");        }        _internal = internal;        _cacheMap = new HashMap(INITIAL_CAPACITY, loadFactor);    }    /**     * Adds the specified value to the cache under the specified key. Note     * that the object is added to both this and the internal cache.     * @param key the (non-null) key to store the object under     * @param value the (non-null) object to place in the cache     * @throws CacheEvictionException exception that the internal cache     *         would have experienced while evicting an object it currently     *         cached.     */    public void put(Object key, Object value) throws CacheEvictionException {        if (key == null) {            throw new IllegalArgumentException("key cannot be null.");        } else if (value == null) {            throw new IllegalArgumentException("value cannot be null.");        }        _internal.put(key, value);        removeClearedEntries();        _cacheMap.put(key, new Entry(key, value, _clearQueue));    }    /**     * Gets the object cached under the specified key.     * <p>     * The cache is looked up in the following manner:     * <ol>     * <li>The internal (L1) cache is checked. If the object is found, it is     *     returned.</li>     * <li>This (L2) cache is checked. If the object is not found, then     *     the caller is informed that the object is inaccessible.</li>     * <li>Since the object exists in L2, but not in L1, the object is     *     readded to L1 using {@link CachePolicy#put(Object, Object)}.</li>     * <li>If the readding succeeds, the value is returned to caller.</li>     * <li>If a cache eviction exception is encountered instead, we     *     remove the object from L2 and behave as if the object was     *     inaccessible.</li>     * </ol>     * @param key the key that the object was stored under.     * @return the object stored under the key specified; null if the     *         object is not (nolonger) accessible via this cache.     */    public Object get(Object key) {        // first try the internal cache.        Object value = _internal.get(key);        if (value != null) {            return value;        }        // poll and remove cleared references.        removeClearedEntries();        Entry entry = (Entry)_cacheMap.get(key);        if (entry == null) { // object is not in cache.            return null;        }        value = entry.getValue();        if (value == null) { // object was in cache, but it was cleared.            return null;        }        // we have the object. so we try to re-insert it into internal cache        try {            _internal.put(key, value);        } catch (CacheEvictionException e) {            // if the internal cache causes a fuss, we kick the object out.            _cacheMap.remove(key);            return null;        }        return value;    }    /**     * Removes any object stored under the key specified. Note that the     * object is removed from both this (L2) and the internal (L1)     * cache.     * @param key the key whose object should be removed     */    public void remove(Object key) {        _cacheMap.remove(key);        _internal.remove(key);    }    /**     * Removes all objects in this (L2) and its internal (L1) cache.     */    public void removeAll() {        _cacheMap.clear();        _internal.removeAll();    }    /**     * Gets all the objects stored by the internal (L1) cache.     * @return an enumeration of objects in internal cache.     */    public Enumeration elements() {        return _internal.elements();    }    /**     * Adds the specified listener to this cache. Note that the events     * fired by this correspond to the <em>internal</em> cache's events.     * @param listener the (non-null) listener to add to this policy     * @throws IllegalArgumentException if listener is null.     */    public void addListener(CachePolicyListener listener)            throws IllegalArgumentException {        _internal.addListener(listener);    }    /**     * Removes a listener that was added earlier.     * @param listener the listener to remove.     */    public void removeListener(CachePolicyListener listener) {        _internal.removeListener(listener);    }    /**     * Cleans the mapping structure of any obsolete entries. This is usually     * called before insertions and lookups on the mapping structure. The     * runtime of this is usually very small, but it can be as expensive as     * n * log(n) if a large number of soft references were recently cleared.     */    private final void removeClearedEntries() {        for (Reference r = _clearQueue.poll(); r != null; r = _clearQueue.poll()) {            Object key = ((Entry)r).getKey();            _cacheMap.remove(key);        }    }    /**     * Value objects we keep in the internal map. This contains the key in     * addition to the value, because polling for cleared references     * returns these instances, and having access to their corresponding     * keys drastically improves the performance of removing the pair     * from the map (see {@link SoftCache#removeClearedEntries()}.)     */    private static class Entry extends SoftReference {        private final Object _key;        /**         * Constructor that uses <code>value</code> as the soft         * reference's referent.         */        public Entry(Object key, Object value, ReferenceQueue queue) {            super(value, queue);            _key = key;        }        /**         * Gets the key         * @return the key associated with this value.         */        final Object getKey() {            return _key;        }        /**         * Gets the value         * @return the value; null if it is no longer accessible         */        final Object getValue() {            return this.get();        }    }}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -