📄 objectpool.java
字号:
/* * 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; } /** * Sets the minimum idle time to release an unused object from the pool. If * the object is not in use and has not been used for this amount of time,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -