📄 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;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -