/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License.
*/ package org.apache.tomcat.dbcp.pool2;
/** * This class consists exclusively of static methods that operate on or return * ObjectPool or KeyedObjectPool related interfaces. * * @since 2.0
*/ publicfinalclass PoolUtils {
/** * Encapsulate the logic for when the next poolable object should be * discarded. Each time update is called, the next time to shrink is * recomputed, based on the float factor, number of idle instances in the * pool and high water mark. Float factor is assumed to be between 0 and 1. * Values closer to 1 cause less frequent erosion events. Erosion event * timing also depends on numIdle. When this value is relatively high (close * to previously established high water mark), erosion occurs more * frequently.
*/ privatestaticfinalclass ErodingFactor { /** Determines frequency of "erosion" events */ privatefinalfloat factor;
/** Time of next shrink event */ privatetransientvolatilelong nextShrinkMillis;
/** High water mark - largest numIdle encountered */ privatetransientvolatileint idleHighWaterMark;
/** * Creates a new ErodingFactor with the given erosion factor. * * @param factor * erosion factor
*/
ErodingFactor(finalfloat factor) { this.factor = factor;
nextShrinkMillis = System.currentTimeMillis() + (long) (900000 * factor); // now + 15 min * factor
idleHighWaterMark = 1;
}
/** * Gets the time of the next erosion event. * * @return next shrink time
*/ publiclong getNextShrink() { return nextShrinkMillis;
}
/** * Updates internal state using the supplied time and numIdle. * * @param nowMillis * current time * @param numIdle * number of idle elements in the pool
*/ publicvoid update(finallong nowMillis, finalint numIdle) { finalint idle = Math.max(0, numIdle);
idleHighWaterMark = Math.max(idle, idleHighWaterMark); finalfloat maxInterval = 15f; finalfloat minutes = maxInterval +
(1f - maxInterval) / idleHighWaterMark * idle;
nextShrinkMillis = nowMillis + (long) (minutes * 60000f * factor);
}
} /** * Decorates a keyed object pool, adding "eroding" behavior. Based on the * configured erosion factor, objects returning to the pool * may be invalidated instead of being added to idle capacity. * * @param <K> object pool key type * @param <V> object pool value type
*/ privatestaticclass ErodingKeyedObjectPool<K, V> implements KeyedObjectPool<K, V> {
/** Underlying pool */ privatefinal KeyedObjectPool<K, V> keyedPool;
/** * Creates an ErodingObjectPool wrapping the given pool using the * specified erosion factor. * * @param keyedPool * underlying pool - must not be null * @param erodingFactor * erosion factor - determines the frequency of erosion * events * @see #erodingFactor
*/ protected ErodingKeyedObjectPool(final KeyedObjectPool<K, V> keyedPool, final ErodingFactor erodingFactor) { if (keyedPool == null) { thrownew IllegalArgumentException(
MSG_NULL_KEYED_POOL);
} this.keyedPool = keyedPool; this.erodingFactor = erodingFactor;
}
/** * Creates an ErodingObjectPool wrapping the given pool using the * specified erosion factor. * * @param keyedPool * underlying pool * @param factor * erosion factor - determines the frequency of erosion * events * @see #erodingFactor
*/
ErodingKeyedObjectPool(final KeyedObjectPool<K, V> keyedPool, finalfloat factor) { this(keyedPool, new ErodingFactor(factor));
}
/** * Gets the eroding factor for the given key * * @param key * key * @return eroding factor for the given keyed pool
*/ protected ErodingFactor getErodingFactor(final K key) { return erodingFactor;
}
/** * Gets the underlying pool * * @return the keyed pool that this ErodingKeyedObjectPool wraps
*/ protected KeyedObjectPool<K, V> getKeyedPool() { return keyedPool;
}
/** * {@inheritDoc}
*/
@Override publicvoid invalidateObject(final K key, final V obj) { try {
keyedPool.invalidateObject(key, obj);
} catch (final Exception ignored) { // ignored
}
}
/** * Returns obj to the pool, unless erosion is triggered, in which case * obj is invalidated. Erosion is triggered when there are idle * instances in the pool associated with the given key and more than the * configured {@link #erodingFactor erosion factor} time has elapsed * since the last returnObject activation. * * @param obj * object to return or invalidate * @param key * key * @see #erodingFactor
*/
@Override publicvoid returnObject(final K key, final V obj) throws Exception { boolean discard = false; finallong nowMillis = System.currentTimeMillis(); final ErodingFactor factor = getErodingFactor(key); synchronized (keyedPool) { if (factor.getNextShrink() < nowMillis) { finalint numIdle = getNumIdle(key); if (numIdle > 0) {
discard = true;
}
/** * Decorates an object pool, adding "eroding" behavior. Based on the * configured {@link #factor erosion factor}, objects returning to the pool * may be invalidated instead of being added to idle capacity. * * @param <T> type of objects in the pool *
*/ privatestaticclass ErodingObjectPool<T> implements ObjectPool<T> {
/** Underlying object pool */ privatefinal ObjectPool<T> pool;
/** * Creates an ErodingObjectPool wrapping the given pool using the * specified erosion factor. * * @param pool * underlying pool * @param factor * erosion factor - determines the frequency of erosion * events * @see #factor
*/
ErodingObjectPool(final ObjectPool<T> pool, finalfloat factor) { this.pool = pool; this.factor = new ErodingFactor(factor);
}
/** * Returns * Gets obj to the pool, unless erosion is triggered, in which case * obj is invalidated. Erosion is triggered when there are idle * instances in the pool and more than the {@link #factor erosion * factor}-determined time has elapsed since the last returnObject * activation. * * @param obj * object to return or invalidate * @see #factor
*/
@Override publicvoid returnObject(final T obj) { boolean discard = false; finallong nowMillis = System.currentTimeMillis(); synchronized (pool) { if (factor.getNextShrink() < nowMillis) { // XXX: Pool 3: move test // out of sync block finalint numIdle = pool.getNumIdle(); if (numIdle > 0) {
discard = true;
}
/** * {@inheritDoc}
*/
@Override public String toString() { return"ErodingObjectPool{" + "factor=" + factor + ", pool=" +
pool + '}';
}
} /** * Extends ErodingKeyedObjectPool to allow erosion to take place on a * per-key basis. Timing of erosion events is tracked separately for * separate keyed pools. * * @param <K> object pool key type * @param <V> object pool value type
*/ privatestaticfinalclass ErodingPerKeyKeyedObjectPool<K, V> extends ErodingKeyedObjectPool<K, V> {
/** Erosion factor - same for all pools */ privatefinalfloat factor;
/** Map of ErodingFactor instances keyed on pool keys */ privatefinal Map<K, ErodingFactor> factors = Collections.synchronizedMap(new HashMap<>());
/** * Creates a new ErordingPerKeyKeyedObjectPool decorating the given keyed * pool with the specified erosion factor. * * @param keyedPool * underlying keyed pool * @param factor * erosion factor
*/
ErodingPerKeyKeyedObjectPool(final KeyedObjectPool<K, V> keyedPool, finalfloat factor) { super(keyedPool, null); this.factor = factor;
}
/** * {@inheritDoc}
*/
@Override protected ErodingFactor getErodingFactor(final K key) { // This may result in two ErodingFactors being created for a key // since they are small and cheap this is okay. return factors.computeIfAbsent(key, k -> new ErodingFactor(this.factor));
}
/** * {@inheritDoc}
*/
@Override public String toString() { return"ErodingPerKeyKeyedObjectPool{" + "factor=" + factor + ", keyedPool=" + getKeyedPool() + '}';
}
} /** * Timer task that adds objects to the pool until the number of idle * instances for the given key reaches the configured minIdle. Note that * this is not the same as the pool's minIdle setting. * * @param <K> object pool key type * @param <V> object pool value type
*/ privatestaticfinalclass KeyedObjectPoolMinIdleTimerTask<K, V> extends TimerTask {
/** Minimum number of idle instances. Not the same as pool.getMinIdle(). */ privatefinalint minIdle;
/** Key to ensure minIdle for */ privatefinal K key;
/** Keyed object pool */ privatefinal KeyedObjectPool<K, V> keyedPool;
/** * Creates a new KeyedObjecPoolMinIdleTimerTask. * * @param keyedPool * keyed object pool * @param key * key to ensure minimum number of idle instances * @param minIdle * minimum number of idle instances * @throws IllegalArgumentException * if the key is null
*/
KeyedObjectPoolMinIdleTimerTask(final KeyedObjectPool<K, V> keyedPool, final K key, finalint minIdle) throws IllegalArgumentException { if (keyedPool == null) { thrownew IllegalArgumentException(
MSG_NULL_KEYED_POOL);
} this.keyedPool = keyedPool; this.key = key; this.minIdle = minIdle;
}
} finally { // detect other types of Throwable and cancel this Timer if (!success) {
cancel();
}
}
}
/** * {@inheritDoc}
*/
@Override public String toString() { final StringBuilder sb = new StringBuilder();
sb.append("KeyedObjectPoolMinIdleTimerTask");
sb.append("{minIdle=").append(minIdle);
sb.append(", key=").append(key);
sb.append(", keyedPool=").append(keyedPool);
sb.append('}'); return sb.toString();
}
} /** * Timer task that adds objects to the pool until the number of idle * instances reaches the configured minIdle. Note that this is not the same * as the pool's minIdle setting. * * @param <T> type of objects in the pool *
*/ privatestaticfinalclass ObjectPoolMinIdleTimerTask<T> extends TimerTask {
/** Minimum number of idle instances. Not the same as pool.getMinIdle(). */ privatefinalint minIdle;
/** Object pool */ privatefinal ObjectPool<T> pool;
/** * Constructs a new ObjectPoolMinIdleTimerTask for the given pool with the * given minIdle setting. * * @param pool * object pool * @param minIdle * number of idle instances to maintain * @throws IllegalArgumentException * if the pool is null
*/
ObjectPoolMinIdleTimerTask(final ObjectPool<T> pool, finalint minIdle) throws IllegalArgumentException { if (pool == null) { thrownew IllegalArgumentException(MSG_NULL_POOL);
} this.pool = pool; this.minIdle = minIdle;
}
} catch (final Exception e) {
cancel();
} finally { // detect other types of Throwable and cancel this Timer if (!success) {
cancel();
}
}
}
/** * {@inheritDoc}
*/
@Override public String toString() { final StringBuilder sb = new StringBuilder();
sb.append("ObjectPoolMinIdleTimerTask");
sb.append("{minIdle=").append(minIdle);
sb.append(", pool=").append(pool);
sb.append('}'); return sb.toString();
}
}
/** * A synchronized (thread-safe) KeyedObjectPool backed by the specified * KeyedObjectPool. * <p> * <b>Note:</b> This should not be used on pool implementations that already * provide proper synchronization such as the pools provided in the Commons * Pool library. Wrapping a pool that {@link #wait() waits} for poolable * objects to be returned before allowing another one to be borrowed with * another layer of synchronization will cause liveliness issues or a * deadlock. * </p> * * @param <K> object pool key type * @param <V> object pool value type
*/ staticfinalclass SynchronizedKeyedObjectPool<K, V> implements KeyedObjectPool<K, V> {
/** * Object whose monitor is used to synchronize methods on the wrapped * pool.
*/ privatefinal ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock();
/** Underlying object pool */ privatefinal KeyedObjectPool<K, V> keyedPool;
/** * Creates a new SynchronizedKeyedObjectPool wrapping the given pool * * @param keyedPool * KeyedObjectPool to wrap * @throws IllegalArgumentException * if keyedPool is null
*/
SynchronizedKeyedObjectPool(final KeyedObjectPool<K, V> keyedPool) throws IllegalArgumentException { if (keyedPool == null) { thrownew IllegalArgumentException(
MSG_NULL_KEYED_POOL);
} this.keyedPool = keyedPool;
}
/** * {@inheritDoc}
*/
@Override publicvoid invalidateObject(final K key, final V obj) { final WriteLock writeLock = readWriteLock.writeLock();
writeLock.lock(); try {
keyedPool.invalidateObject(key, obj);
} catch (final Exception ignored) { // ignored as of Pool 2
} finally {
writeLock.unlock();
}
}
/** * {@inheritDoc}
*/
@Override publicvoid returnObject(final K key, final V obj) { final WriteLock writeLock = readWriteLock.writeLock();
writeLock.lock(); try {
keyedPool.returnObject(key, obj);
} catch (final Exception ignored) { // ignored
} finally {
writeLock.unlock();
}
}
/** * {@inheritDoc}
*/
@Override public String toString() { final StringBuilder sb = new StringBuilder();
sb.append("SynchronizedKeyedObjectPool");
sb.append("{keyedPool=").append(keyedPool);
sb.append('}'); return sb.toString();
}
}
/** * A fully synchronized KeyedPooledObjectFactory that wraps a * KeyedPooledObjectFactory and synchronizes access to the wrapped factory * methods. * <p> * <b>Note:</b> This should not be used on pool implementations that already * provide proper synchronization such as the pools provided in the Commons * Pool library. * </p> * * @param <K> pooled object factory key type * @param <V> pooled object factory value type
*/ privatestaticfinalclass SynchronizedKeyedPooledObjectFactory<K, V> implements KeyedPooledObjectFactory<K, V> {
/** Synchronization lock */ privatefinal WriteLock writeLock = new ReentrantReadWriteLock().writeLock();
/** * Creates a SynchronizedKeyedPooledObjectFactory wrapping the given * factory. * * @param keyedFactory * underlying factory to wrap * @throws IllegalArgumentException * if the factory is null
*/
SynchronizedKeyedPooledObjectFactory(final KeyedPooledObjectFactory<K, V> keyedFactory) throws IllegalArgumentException { if (keyedFactory == null) { thrownew IllegalArgumentException( "keyedFactory must not be null.");
} this.keyedFactory = keyedFactory;
}
/** * A synchronized (thread-safe) ObjectPool backed by the specified * ObjectPool. * <p> * <b>Note:</b> This should not be used on pool implementations that already * provide proper synchronization such as the pools provided in the Commons * Pool library. Wrapping a pool that {@link #wait() waits} for poolable * objects to be returned before allowing another one to be borrowed with * another layer of synchronization will cause liveliness issues or a * deadlock. * </p> * * @param <T> type of objects in the pool *
*/ privatestaticfinalclass SynchronizedObjectPool<T> implements ObjectPool<T> {
/** * Object whose monitor is used to synchronize methods on the wrapped * pool.
*/ privatefinal ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock();
/** the underlying object pool */ privatefinal ObjectPool<T> pool;
/** * Creates a new SynchronizedObjectPool wrapping the given pool. * * @param pool * the ObjectPool to be "wrapped" in a synchronized * ObjectPool. * @throws IllegalArgumentException * if the pool is null
*/
SynchronizedObjectPool(final ObjectPool<T> pool) throws IllegalArgumentException { if (pool == null) { thrownew IllegalArgumentException(MSG_NULL_POOL);
} this.pool = pool;
}
/** * {@inheritDoc}
*/
@Override publicvoid invalidateObject(final T obj) { final WriteLock writeLock = readWriteLock.writeLock();
writeLock.lock(); try {
pool.invalidateObject(obj);
} catch (final Exception ignored) { // ignored as of Pool 2
} finally {
writeLock.unlock();
}
}
/** * {@inheritDoc}
*/
@Override publicvoid returnObject(final T obj) { final WriteLock writeLock = readWriteLock.writeLock();
writeLock.lock(); try {
pool.returnObject(obj);
} catch (final Exception ignored) { // ignored as of Pool 2
} finally {
writeLock.unlock();
}
}
/** * {@inheritDoc}
*/
@Override public String toString() { final StringBuilder sb = new StringBuilder();
sb.append("SynchronizedObjectPool");
sb.append("{pool=").append(pool);
sb.append('}'); return sb.toString();
}
}
/** * A fully synchronized PooledObjectFactory that wraps a * PooledObjectFactory and synchronizes access to the wrapped factory * methods. * <p> * <b>Note:</b> This should not be used on pool implementations that already * provide proper synchronization such as the pools provided in the Commons * Pool library. * </p> * * @param <T> pooled object factory type
*/ privatestaticfinalclass SynchronizedPooledObjectFactory<T> implements
PooledObjectFactory<T> {
/** Synchronization lock */ privatefinal WriteLock writeLock = new ReentrantReadWriteLock().writeLock();
/** * Creates a SynchronizedPoolableObjectFactory wrapping the given * factory. * * @param factory * underlying factory to wrap * @throws IllegalArgumentException * if the factory is null
*/
SynchronizedPooledObjectFactory(final PooledObjectFactory<T> factory) throws IllegalArgumentException { if (factory == null) { thrownew IllegalArgumentException("factory must not be null.");
} this.factory = factory;
}
/** * Timer used to periodically check pools idle object count. Because a * {@link Timer} creates a {@link Thread}, an IODH is used.
*/ staticclass TimerHolder { staticfinal Timer MIN_IDLE_TIMER = new Timer(true);
}
privatestaticfinal String MSG_FACTOR_NEGATIVE = "factor must be positive.";
privatestaticfinal String MSG_MIN_IDLE = "minIdle must be non-negative.";
staticfinal String MSG_NULL_KEY = "key must not be null.";
privatestaticfinal String MSG_NULL_KEYED_POOL = "keyedPool must not be null.";
staticfinal String MSG_NULL_KEYS = "keys must not be null.";
privatestaticfinal String MSG_NULL_POOL = "pool must not be null.";
/** * Periodically check the idle object count for each key in the * {@code Collection keys} in the keyedPool. At most one idle object will be * added per period. * * @param keyedPool * the keyedPool to check periodically. * @param keys * a collection of keys to check the idle object count. * @param minIdle * if the {@link KeyedObjectPool#getNumIdle(Object)} is less than * this then add an idle object. * @param periodMillis * the frequency in milliseconds to check the number of idle objects in a * keyedPool, see {@link Timer#schedule(TimerTask, long, long)}. * @param <K> the type of the pool key * @param <V> the type of pool entries * * @return a {@link Map} of key and {@link TimerTask} pairs that will * periodically check the pools idle object count. * @throws IllegalArgumentException * when {@code keyedPool}, {@code keys}, or any of the values in * the collection is {@code null} or when {@code minIdle} is * negative or when {@code period} isn't valid for * {@link Timer#schedule(TimerTask, long, long)}. * @see #checkMinIdle(KeyedObjectPool, Object, int, long)
*/ publicstatic <K, V> Map<K, TimerTask> checkMinIdle( final KeyedObjectPool<K, V> keyedPool, final Collection<K> keys, finalint minIdle, finallong periodMillis) throws IllegalArgumentException { if (keys == null) { thrownew IllegalArgumentException(MSG_NULL_KEYS);
} final Map<K, TimerTask> tasks = new HashMap<>(keys.size()); for (K key : keys) { final TimerTask task = checkMinIdle(keyedPool, key, minIdle, periodMillis);
tasks.put(key, task);
} return tasks;
}
/** * Periodically check the idle object count for the key in the keyedPool. At * most one idle object will be added per period. If there is an exception * when calling {@link KeyedObjectPool#addObject(Object)} then no more * checks for that key will be performed. * * @param keyedPool * the keyedPool to check periodically. * @param key * the key to check the idle count of. * @param minIdle * if the {@link KeyedObjectPool#getNumIdle(Object)} is less than * this then add an idle object. * @param periodMillis * the frequency in milliseconds to check the number of idle objects in a * keyedPool, see {@link Timer#schedule(TimerTask, long, long)}. * @param <K> the type of the pool key * @param <V> the type of pool entries * * @return the {@link TimerTask} that will periodically check the pools idle * object count. * @throws IllegalArgumentException * when {@code keyedPool}, {@code key} is {@code null} or * when {@code minIdle} is negative or when {@code period} isn't * valid for {@link Timer#schedule(TimerTask, long, long)}.
*/ publicstatic <K, V> TimerTask checkMinIdle( final KeyedObjectPool<K, V> keyedPool, final K key, finalint minIdle, finallong periodMillis) throws IllegalArgumentException { if (keyedPool == null) { thrownew IllegalArgumentException(MSG_NULL_KEYED_POOL);
} if (key == null) { thrownew IllegalArgumentException(MSG_NULL_KEY);
} if (minIdle < 0) { thrownew IllegalArgumentException(MSG_MIN_IDLE);
} final TimerTask task = new KeyedObjectPoolMinIdleTimerTask<>(
keyedPool, key, minIdle);
getMinIdleTimer().schedule(task, 0L, periodMillis); return task;
}
/** * Periodically check the idle object count for the pool. At most one idle * object will be added per period. If there is an exception when calling * {@link ObjectPool#addObject()} then no more checks will be performed. * * @param pool * the pool to check periodically. * @param minIdle * if the {@link ObjectPool#getNumIdle()} is less than this then * add an idle object. * @param periodMillis * the frequency in milliseconds to check the number of idle objects in a pool, * see {@link Timer#schedule(TimerTask, long, long)}. * @param <T> the type of objects in the pool * * @return the {@link TimerTask} that will periodically check the pools idle * object count. * @throws IllegalArgumentException * when {@code pool} is {@code null} or when {@code minIdle} is * negative or when {@code period} isn't valid for * {@link Timer#schedule(TimerTask, long, long)}
*/ publicstatic <T> TimerTask checkMinIdle(final ObjectPool<T> pool, finalint minIdle, finallong periodMillis) throws IllegalArgumentException { if (pool == null) { thrownew IllegalArgumentException(MSG_NULL_KEYED_POOL);
} if (minIdle < 0) { thrownew IllegalArgumentException(MSG_MIN_IDLE);
} final TimerTask task = new ObjectPoolMinIdleTimerTask<>(pool, minIdle);
getMinIdleTimer().schedule(task, 0L, periodMillis); return task;
}
/** * Should the supplied Throwable be re-thrown (eg if it is an instance of * one of the Throwables that should never be swallowed). Used by the pool * error handling for operations that throw exceptions that normally need to * be ignored. * * @param t * The Throwable to check * @throws ThreadDeath * if that is passed in * @throws VirtualMachineError * if that is passed in
*/ publicstaticvoid checkRethrow(final Throwable t) { if (t instanceof ThreadDeath) { throw (ThreadDeath) t;
} if (t instanceof VirtualMachineError) { throw (VirtualMachineError) t;
} // All other instances of Throwable will be silently swallowed
}
/** * Returns a pool that adaptively decreases its size when idle objects are * no longer needed. This is intended as an always thread-safe alternative * to using an idle object evictor provided by many pool implementations. * This is also an effective way to shrink FIFO ordered pools that * experience load spikes. * * @param keyedPool * the KeyedObjectPool to be decorated so it shrinks its idle * count when possible. * @param <K> the type of the pool key * @param <V> the type of pool entries * * @throws IllegalArgumentException * when {@code keyedPool} is {@code null}. * @return a pool that adaptively decreases its size when idle objects are * no longer needed. * @see #erodingPool(KeyedObjectPool, float) * @see #erodingPool(KeyedObjectPool, float, boolean)
*/ publicstatic <K, V> KeyedObjectPool<K, V> erodingPool(final KeyedObjectPool<K, V> keyedPool) { return erodingPool(keyedPool, 1f);
}
/** * Returns a pool that adaptively decreases its size when idle objects are * no longer needed. This is intended as an always thread-safe alternative * to using an idle object evictor provided by many pool implementations. * This is also an effective way to shrink FIFO ordered pools that * experience load spikes. * <p> * The factor parameter provides a mechanism to tweak the rate at which the * pool tries to shrink its size. Values between 0 and 1 cause the pool to * try to shrink its size more often. Values greater than 1 cause the pool * to less frequently try to shrink its size. * </p> * * @param keyedPool * the KeyedObjectPool to be decorated so it shrinks its idle * count when possible. * @param factor * a positive value to scale the rate at which the pool tries to * reduce its size. If 0 < factor < 1 then the pool * shrinks more aggressively. If 1 < factor then the pool * shrinks less aggressively. * @param <K> the type of the pool key * @param <V> the type of pool entries * * @throws IllegalArgumentException * when {@code keyedPool} is {@code null} or when {@code factor} * is not positive. * @return a pool that adaptively decreases its size when idle objects are * no longer needed. * @see #erodingPool(KeyedObjectPool, float, boolean)
*/ publicstatic <K, V> KeyedObjectPool<K, V> erodingPool(final KeyedObjectPool<K, V> keyedPool, finalfloat factor) { return erodingPool(keyedPool, factor, false);
}
/** * Returns a pool that adaptively decreases its size when idle objects are * no longer needed. This is intended as an always thread-safe alternative * to using an idle object evictor provided by many pool implementations. * This is also an effective way to shrink FIFO ordered pools that * experience load spikes. * <p> * The factor parameter provides a mechanism to tweak the rate at which the * pool tries to shrink its size. Values between 0 and 1 cause the pool to * try to shrink its size more often. Values greater than 1 cause the pool * to less frequently try to shrink its size. * </p> * <p> * The perKey parameter determines if the pool shrinks on a whole pool basis * or a per key basis. When perKey is false, the keys do not have an effect * on the rate at which the pool tries to shrink its size. When perKey is * true, each key is shrunk independently. * </p> * * @param keyedPool * the KeyedObjectPool to be decorated so it shrinks its idle * count when possible. * @param factor * a positive value to scale the rate at which the pool tries to * reduce its size. If 0 < factor < 1 then the pool * shrinks more aggressively. If 1 < factor then the pool * shrinks less aggressively. * @param perKey * when true, each key is treated independently. * @param <K> the type of the pool key * @param <V> the type of pool entries * * @throws IllegalArgumentException * when {@code keyedPool} is {@code null} or when {@code factor} * is not positive. * @return a pool that adaptively decreases its size when idle objects are * no longer needed. * @see #erodingPool(KeyedObjectPool) * @see #erodingPool(KeyedObjectPool, float)
*/ publicstatic <K, V> KeyedObjectPool<K, V> erodingPool( final KeyedObjectPool<K, V> keyedPool, finalfloat factor, finalboolean perKey) { if (keyedPool == null) { thrownew IllegalArgumentException(MSG_NULL_KEYED_POOL);
} if (factor <= 0f) { thrownew IllegalArgumentException(MSG_FACTOR_NEGATIVE);
} if (perKey) { returnnew ErodingPerKeyKeyedObjectPool<>(keyedPool, factor);
} returnnew ErodingKeyedObjectPool<>(keyedPool, factor);
}
/** * Returns a pool that adaptively decreases its size when idle objects are * no longer needed. This is intended as an always thread-safe alternative * to using an idle object evictor provided by many pool implementations. * This is also an effective way to shrink FIFO ordered pools that * experience load spikes. * * @param pool * the ObjectPool to be decorated so it shrinks its idle count * when possible. * @param <T> the type of objects in the pool * * @throws IllegalArgumentException * when {@code pool} is {@code null}. * @return a pool that adaptively decreases its size when idle objects are * no longer needed. * @see #erodingPool(ObjectPool, float)
*/ publicstatic <T> ObjectPool<T> erodingPool(final ObjectPool<T> pool) { return erodingPool(pool, 1f);
}
/** * Returns a pool that adaptively decreases its size when idle objects are * no longer needed. This is intended as an always thread-safe alternative * to using an idle object evictor provided by many pool implementations. * This is also an effective way to shrink FIFO ordered pools that * experience load spikes. * <p> * The factor parameter provides a mechanism to tweak the rate at which the * pool tries to shrink its size. Values between 0 and 1 cause the pool to * try to shrink its size more often. Values greater than 1 cause the pool * to less frequently try to shrink its size. * </p> * * @param pool * the ObjectPool to be decorated so it shrinks its idle count * when possible. * @param factor * a positive value to scale the rate at which the pool tries to * reduce its size. If 0 < factor < 1 then the pool * shrinks more aggressively. If 1 < factor then the pool * shrinks less aggressively. * @param <T> the type of objects in the pool * * @throws IllegalArgumentException * when {@code pool} is {@code null} or when {@code factor} is * not positive. * @return a pool that adaptively decreases its size when idle objects are * no longer needed. * @see #erodingPool(ObjectPool)
*/ publicstatic <T> ObjectPool<T> erodingPool(final ObjectPool<T> pool, finalfloat factor) { if (pool == null) { thrownew IllegalArgumentException(MSG_NULL_POOL);
} if (factor <= 0f) { thrownew IllegalArgumentException(MSG_FACTOR_NEGATIVE);
} returnnew ErodingObjectPool<>(pool, factor);
}
/** * Gets the {@code Timer} for checking keyedPool's idle count. * * @return the {@link Timer} for checking keyedPool's idle count.
*/ privatestatic Timer getMinIdleTimer() { return TimerHolder.MIN_IDLE_TIMER;
}
/** * Calls {@link KeyedObjectPool#addObject(Object)} on {@code keyedPool} with * each key in {@code keys} for {@code count} number of times. This has * the same effect as calling {@link #prefill(KeyedObjectPool, Object, int)} * for each key in the {@code keys} collection. * * @param keyedPool * the keyedPool to prefill. * @param keys * {@link Collection} of keys to add objects for. * @param count * the number of idle objects to add for each {@code key}. * @param <K> the type of the pool key * @param <V> the type of pool entries * * @throws Exception * when {@link KeyedObjectPool#addObject(Object)} fails. * @throws IllegalArgumentException * when {@code keyedPool}, {@code keys}, or any value in * {@code keys} is {@code null}. * @see #prefill(KeyedObjectPool, Object, int) * @deprecated Use {@link KeyedObjectPool#addObjects(Collection, int)}.
*/
@Deprecated publicstatic <K, V> void prefill(final KeyedObjectPool<K, V> keyedPool, final Collection<K> keys, finalint count) throws Exception,
IllegalArgumentException { if (keys == null) { thrownew IllegalArgumentException(MSG_NULL_KEYS);
}
keyedPool.addObjects(keys, count);
}
/** * Calls {@link KeyedObjectPool#addObject(Object)} on {@code keyedPool} with * {@code key} {@code count} number of times. * * @param keyedPool * the keyedPool to prefill. * @param key * the key to add objects for. * @param count * the number of idle objects to add for {@code key}. * @param <K> the type of the pool key * @param <V> the type of pool entries * * @throws Exception * when {@link KeyedObjectPool#addObject(Object)} fails. * @throws IllegalArgumentException * when {@code keyedPool} or {@code key} is {@code null}. * @deprecated Use {@link KeyedObjectPool#addObjects(Object, int)}.
*/
@Deprecated publicstatic <K, V> void prefill(final KeyedObjectPool<K, V> keyedPool, final K key, finalint count) throws Exception,
IllegalArgumentException { if (keyedPool == null) { thrownew IllegalArgumentException(MSG_NULL_KEYED_POOL);
}
keyedPool.addObjects(key, count);
}
/** * Calls {@link ObjectPool#addObject()} on {@code pool} {@code count} number * of times. * * @param pool * the pool to prefill. * @param count * the number of idle objects to add. * @param <T> the type of objects in the pool * * @throws Exception * when {@link ObjectPool#addObject()} fails. * @throws IllegalArgumentException * when {@code pool} is {@code null}. * @deprecated Use {@link ObjectPool#addObjects(int)}.
*/
@Deprecated publicstatic <T> void prefill(final ObjectPool<T> pool, finalint count) throws Exception { if (pool == null) { thrownew IllegalArgumentException(MSG_NULL_POOL);
}
pool.addObjects(count);
}
/** * Returns a synchronized (thread-safe) KeyedPooledObjectFactory backed by * the specified KeyedPooledObjectFactory. * * @param keyedFactory * the KeyedPooledObjectFactory to be "wrapped" in a * synchronized KeyedPooledObjectFactory. * @param <K> the type of the pool key * @param <V> the type of pool entries * @return a synchronized view of the specified KeyedPooledObjectFactory.
*/ publicstatic <K, V> KeyedPooledObjectFactory<K, V> synchronizedKeyedPooledFactory( final KeyedPooledObjectFactory<K, V> keyedFactory) { returnnew SynchronizedKeyedPooledObjectFactory<>(keyedFactory);
}
/** * Returns a synchronized (thread-safe) KeyedObjectPool backed by the * specified KeyedObjectPool. * <p> * <b>Note:</b> This should not be used on pool implementations that already * provide proper synchronization such as the pools provided in the Commons * Pool library. Wrapping a pool that {@link #wait() waits} for poolable * objects to be returned before allowing another one to be borrowed with * another layer of synchronization will cause liveliness issues or a * deadlock. * </p> * * @param keyedPool * the KeyedObjectPool to be "wrapped" in a synchronized * KeyedObjectPool. * @param <K> the type of the pool key * @param <V> the type of pool entries * * @return a synchronized view of the specified KeyedObjectPool.
*/ publicstatic <K, V> KeyedObjectPool<K, V> synchronizedPool(final KeyedObjectPool<K, V> keyedPool) { /* * assert !(keyedPool instanceof GenericKeyedObjectPool) : * "GenericKeyedObjectPool is already thread-safe"; assert !(keyedPool * instanceof StackKeyedObjectPool) : * "StackKeyedObjectPool is already thread-safe"; assert * !"org.apache.commons.pool.composite.CompositeKeyedObjectPool" * .equals(keyedPool.getClass().getName()) : * "CompositeKeyedObjectPools are already thread-safe";
*/ returnnew SynchronizedKeyedObjectPool<>(keyedPool);
}
/** * Returns a synchronized (thread-safe) ObjectPool backed by the specified * ObjectPool. * <p> * <b>Note:</b> This should not be used on pool implementations that already * provide proper synchronization such as the pools provided in the Commons * Pool library. Wrapping a pool that {@link #wait() waits} for poolable * objects to be returned before allowing another one to be borrowed with * another layer of synchronization will cause liveliness issues or a * deadlock. * </p> * * @param <T> the type of objects in the pool * @param pool * the ObjectPool to be "wrapped" in a synchronized ObjectPool. * @throws IllegalArgumentException * when {@code pool} is {@code null}. * @return a synchronized view of the specified ObjectPool.
*/ publicstatic <T> ObjectPool<T> synchronizedPool(final ObjectPool<T> pool) { if (pool == null) { thrownew IllegalArgumentException(MSG_NULL_POOL);
}
/** * Returns a synchronized (thread-safe) PooledObjectFactory backed by the * specified PooledObjectFactory. * * @param factory * the PooledObjectFactory to be "wrapped" in a synchronized * PooledObjectFactory. * @param <T> the type of objects in the pool * @return a synchronized view of the specified PooledObjectFactory.
*/ publicstatic <T> PooledObjectFactory<T> synchronizedPooledFactory(final PooledObjectFactory<T> factory) { returnnew SynchronizedPooledObjectFactory<>(factory);
}
/** * PoolUtils instances should NOT be constructed in standard programming. * Instead, the class should be used procedurally: PoolUtils.adapt(aPool);. * This constructor is public to permit tools that require a JavaBean * instance to operate.
*/ public PoolUtils() {
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.