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

📄 objectpool.java

📁 国外的一套开源CRM
💻 JAVA
📖 第 1 页 / 共 3 页
字号:
/*
 * Licensed under the X license (see http://www.x.org/terms.htm)
 */
package org.ofbiz.minerva.pool;


import EDU.oswego.cs.dl.util.concurrent.FIFOSemaphore;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.ConcurrentModificationException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

import org.apache.log4j.Logger;

/**
 * A generic object pool.  You must provide a PoolObjectFactory (or the class
 * of a Java Bean) so the pool knows what kind of objects to create.  It has
 * many configurable parameters, such as the minimum and maximum size of the
 * pool, whether to enable idle timeouts, etc.  If the pooled objects
 * implement PooledObject, they will automatically be returned to the pool at
 * the appropriate times.
 * <P>In general, the appropriate way to use a pool is:</P>
 * <OL>
 *   <LI>Create it</LI>
 *   <LI>Configure it (set factory, name, parameters, etc.)</LI>
 *   <LI>Initialize it (once done, further configuration is not allowed)</LI>
 *   <LI>Use it</LI>
 *   <LI>Shut it down</LI>
 * </OL>
 * @see org.ofbiz.minerva.pool.PooledObject
 *
 * @author Aaron Mulder (ammulder@alumni.princeton.edu)
 * @author <a href="mailto:danch@nvisia.com">danch (Dan Christopherson)</a>
 *
 * Revision:
 * 20010701 danch added code for timeout in blocking.
 */
public class ObjectPool implements PoolEventListener {

    private final static String INITIALIZED = "Pool already initialized!";
    private final static PoolGCThread collector = new PoolGCThread();

    static {
        collector.start();
    }

    private Logger log = Logger.getLogger(ObjectPool.class);
    private PoolObjectFactory factory;
    private String poolName;

    private final Map objects = new HashMap();
    private final Set deadObjects = Collections.synchronizedSet(new HashSet());
    private int minSize = 0;
    private int maxSize = 0;
    private boolean idleTimeout = false;
    private boolean runGC = false;
    private float maxIdleShrinkPercent = 1.0f; // don't replace idle connections that timeout
    private long idleTimeoutMillis = 1800000l; // must be idle in pool for 30 minutes
    private long gcMinIdleMillis = 1200000l; // must be unused by client for 20 minutes
    private long gcIntervalMillis = 120000l; // shrink & gc every 2 minutes
    private long lastGC = System.currentTimeMillis();
    private boolean blocking = true;
    private int blockingTimeout = 10000;//Integer.MAX_VALUE;//this is silly
    private boolean trackLastUsed = false;
    private boolean invalidateOnError = false;

    private FIFOSemaphore permits;
    private boolean initialized = false;

    /**
     * Creates a new pool.  It cannot be used until you specify a name and
     * object factory or bean class, and initialize it.
     * @see #setName
     * @see #setObjectFactory
     * @see #initialize
     */
    public ObjectPool() {
    }

    /**
     * Creates a new pool with the specified parameters.  It cannot be used
     * until you initialize it.
     * @param factory The object factory that will create the objects to go in
     *    the pool.
     * @param poolName The name of the pool.  This does not have to be unique
     *    across all pools, but it is strongly recommended (and it may be a
     *    requirement for certain uses of the pool).
     * @see #initialize
     */
    public ObjectPool(PoolObjectFactory factory, String poolName) {
        setObjectFactory(factory);
        setName(poolName);
    }

    /**
     * Creates a new pool with the specified parameters.  It cannot be used
     * until you initialize it.
     * @param javaBeanClass The Class of a Java Bean.  New instances for the
     *    pool will be created with the no-argument constructor, and no
     *    particular initialization or cleanup will be performed on the
     *    instances.  Use a PoolObjectFactory if you want more control over
     *    the instances.
     * @param poolName The name of the pool.  This does not have to be unique
     *    across all pools, but it is strongly recommended (and it may be a
     *    requirement for certain uses of the pool).
     * @see #initialize
     */
    public ObjectPool(Class javaBeanClass, String poolName) {
        setObjectFactory(javaBeanClass);
        setName(poolName);
    }

    /**
     * Sets the object factory for the pool.  The object factory controls the
     * instances created for the pool, and can initialize instances given out
     * by the pool and cleanup instances returned to the pool.
     * @throws java.lang.IllegalStateException
     *    Occurs when you try to set the object factory after the pool has been
     *    initialized.
     */
    public void setObjectFactory(PoolObjectFactory factory) {
        if (initialized)
            throw new IllegalStateException(INITIALIZED);
        this.factory = factory;
    }

    /**
     * Sets the object factory as a new factory for Java Beans.  New instances
     *    for the pool will be created with the no-argument constructor, and no
     *    particular initialization or cleanup will be performed on the
     *    instances.
     * @throws java.lang.IllegalStateException
     *    Occurs when you try to set the object factory after the pool has been
     *    initialized.
     */
    public void setObjectFactory(Class javaBeanClass) {
        if (initialized)
            throw new IllegalStateException(INITIALIZED);
        factory = new BeanFactory(javaBeanClass);
    }

    /**
     * Sets the name of the pool.  This is not required to be unique across all
     * pools, but is strongly recommended.  Certain uses of the pool (such as
     * a JNDI object factory) may require it.  This must be set exactly once
     * for each pool (it may be set in the constructor).
     * @throws java.lang.IllegalStateException
     *    Occurs when you try to set the name of the pool more than once.
     */
    public void setName(String name) {
        if (name == null || name.length() == 0)
            throw new IllegalArgumentException("Cannot set pool name to null or empty!");
        if (poolName != null && !poolName.equals(name))
            throw new IllegalStateException("Cannot change pool name once set!");
        poolName = name;
        log = Logger.getLogger(ObjectPool.class.getName() + "." + name);
    }

    /**
     * Gets the name of the pool.
     */
    public String getName() {
        return poolName;
    }

    /**
     * Sets the minimum size of the pool.  The pool will create this many
     * instances at startup, and once running, it will never shrink below this
     * size.  The default is zero.
     * @throws java.lang.IllegalStateException
     *    Occurs when you try to set the minimum size after the pool has been
     *    initialized.
     */
    public void setMinSize(int size) {
        if (initialized)
            throw new IllegalStateException(INITIALIZED);
        minSize = size;
        if (maxSize != 0 && minSize > maxSize) {
            maxSize = minSize;
            log.warn("pool max size set to " + maxSize + " to stay >= min size");
        }
    }

    /**
     * Gets the minimum size of the pool.
     * @see #setMinSize
     */
    public int getMinSize() {
        return minSize;
    }

    /**
     * Sets the maximum size of the pool.  Once the pool has grown to hold this
     * number of instances, it will not add any more instances.  If one of the
     * pooled instances is available when a request comes in, it will be
     * returned.  If none of the pooled instances are available, the pool will
     * either block until an instance is available, or return null.  The default
     * is no maximum size.
     * @see #setBlocking
     * @param size The maximum size of the pool, or 0 if the pool should grow
     *    indefinitely (not recommended).
     * @throws java.lang.IllegalStateException
     *    Occurs when you try to set the maximum size after the pool has been
     *    initialized.
     */
    public void setMaxSize(int size) {
        if (initialized)
            throw new IllegalStateException(INITIALIZED);
        maxSize = size;
        if (maxSize != 0 && minSize > maxSize) {
            minSize = maxSize;
            log.warn("pool min size set to " + minSize + " to stay <= max size");
        }
    }

    /**
     * Gets the maximum size of the pool.
     * @see #setMaxSize
     */
    public int getMaxSize() {
        return maxSize;
    }

    /**
     * Sets whether the pool should release instances that have not been used
     * recently.  This is intended to reclaim resources (memory, database
     * connections, file handles, etc) during periods of inactivity.  This runs
     * as often as garbage collection (even if garbage collection is disabled,
     * this uses the same timing parameter), but the required period of
     * inactivity is different.  All objects that have been unused for more
     * than the idle timeout are closed, but if you set the MaxIdleShrinkPercent
     * parameter, the pool may recreate some objects so the total number of
     * pooled instances doesn't shrink as rapidly. Also, under no circumstances
     * will the number of pooled instances fall below the minimum size.</p>
     * <P>The default is disabled.</P>
     * @see #setGCInterval
     * @see #setIdleTimeout
     * @see #setMaxIdleTimeoutPercent
     * @see #setMinSize
     * @throws java.lang.IllegalStateException
     *    Occurs when you try to set the idle timeout state after the pool has
     *    been initialized.
     */
    public void setIdleTimeoutEnabled(boolean enableTimeout) {
        if (initialized)
            throw new IllegalStateException(INITIALIZED);
        idleTimeout = enableTimeout;
    }

    /**
     * Gets whether the pool releases instances that have not been used
     * recently.  This is different than garbage collection, which returns
     * instances to the pool if a client checked an instance out but has not
     * used it and not returned it to the pool.
     * @see #setIdleTimeoutEnabled
     */
    public boolean isIdleTimeoutEnabled() {
        return idleTimeout;
    }

    /**
     * Sets whether garbage collection is enabled.  This is the process of
     * returning objects to the pool if they have been checked out of the pool
     * but have not been used in a long periond of time.  This is meant to
     * reclaim resources, generally caused by unexpected failures on the part
     * of the pool client (which forestalled returning an object to the pool).
     * This runs on the same schedule as the idle timeout (if enabled), but
     * objects that were just garbage collected will not be eligible for the
     * idle timeout immediately (after all, they presumably represented "active"
     * clients).  Objects that are garbage collected will be checked out again
     * immediately if a client is blocking waiting for an object.  The default
     * value is disabled.
     * @see #setGCMinIdleTime
     * @see #setGCInterval
     * @throws java.lang.IllegalStateException
     *    Occurs when you try to set the garbage collection state after the pool
     *    has been initialized.
     */
    public void setGCEnabled(boolean enabled) {
        if (initialized)
            throw new IllegalStateException(INITIALIZED);
        runGC = enabled;
    }

    /**
     * Gets whether garbage collection is enabled.
     * @see #setGCEnabled
     */
    public boolean isGCEnabled() {
        return runGC;
    }

    /**
     * Sets the idle timeout percent as a fraction between 0 and 1.  If a number
     * of objects are determined to be idle, they will all be closed and
     * removed from the pool.  However, if the ratio of objects released to
     * objects in the pool is greater than this fraction, some new objects
     * will be created to replace the closed objects.  This prevents the pool
     * size from decreasing too rapidly.  Set to 0 to decrease the pool size by
     * a maximum of 1 object per test, or 1 to never replace objects that have
     * exceeded the idle timeout.  The pool will always replace enough closed
     * connections to stay at the minimum size.
     * @see #setIdleTimeoutEnabled
     * @throws java.lang.IllegalStateException
     *    Occurs when you try to set the idle timeout percent after the pool
     *    has been initialized.
     * @throws java.lang.IllegalArgumentException
     *    Occurs when the percent parameter is not between 0 and 1.
     */
    public void setMaxIdleTimeoutPercent(float percent) {
        if (initialized)
            throw new IllegalStateException(INITIALIZED);
        if (percent < 0f || percent > 1f)
            throw new IllegalArgumentException("Percent must be between 0 and 1!");
        maxIdleShrinkPercent = percent;
    }

    /**
     * Gets the idle timeout percent as a fraction between 0 and 1.
     * @see #setMaxIdleTimeoutPercent
     */
    public float getMaxIdleTimeoutPercent() {
        return maxIdleShrinkPercent;
    }

⌨️ 快捷键说明

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