/*
* 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.commons.pool2;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock;
import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock;
This class consists exclusively of static methods that operate on or return
ObjectPool or KeyedObjectPool related interfaces.
Since: 2.0
/**
* This class consists exclusively of static methods that operate on or return
* ObjectPool or KeyedObjectPool related interfaces.
*
* @since 2.0
*/
public final class PoolUtils {
private static final String MSG_FACTOR_NEGATIVE = "factor must be positive.";
private static final String MSG_MIN_IDLE = "minIdle must be non-negative.";
private static final String MSG_NULL_KEY = "key must not be null.";
private static final String MSG_NULL_KEYED_POOL = "keyedPool must not be null.";
private static final String MSG_NULL_KEYS = "keys must not be null.";
private static final String MSG_NULL_POOL = "pool must not be null.";
/**
* Timer used to periodically check pools idle object count. Because a
* {@link Timer} creates a {@link Thread}, an IODH is used.
*/
static class TimerHolder {
static final Timer MIN_IDLE_TIMER = new Timer(true);
}
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.
/**
* 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() {
}
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.
Params: - t –
The Throwable to check
Throws: - ThreadDeath –
if that is passed in
- VirtualMachineError –
if that is passed in
/**
* 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
*/
public static void 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
}
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 ObjectPool.addObject()
then no more checks will be performed. Params: - pool –
the pool to check periodically.
- minIdle – if the
ObjectPool.getNumIdle()
is less than this then add an idle object. - period – the frequency to check the number of idle objects in a pool, see
Timer.schedule(TimerTask, long, long)
.
Type parameters: - <T> – the type of objects in the pool
Throws: - IllegalArgumentException –
when
pool
is null
or when
minIdle
is negative or when period
isn't valid for Timer.schedule(TimerTask, long, long)
Returns: the TimerTask
that will periodically check the pools idle object count.
/**
* 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 period
* the frequency 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</code> is <code>null</code> or when
* <code>minIdle</code> is negative or when <code>period</code>
* isn't valid for {@link Timer#schedule(TimerTask, long, long)}
*/
public static <T> TimerTask checkMinIdle(final ObjectPool<T> pool,
final int minIdle, final long period)
throws IllegalArgumentException {
if (pool == null) {
throw new IllegalArgumentException(MSG_NULL_KEYED_POOL);
}
if (minIdle < 0) {
throw new IllegalArgumentException(MSG_MIN_IDLE);
}
final TimerTask task = new ObjectPoolMinIdleTimerTask<>(pool, minIdle);
getMinIdleTimer().schedule(task, 0L, period);
return task;
}
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 KeyedObjectPool.addObject(Object)
then no more checks for that key will be performed. Params: - keyedPool –
the keyedPool to check periodically.
- key –
the key to check the idle count of.
- minIdle – if the
KeyedObjectPool.getNumIdle(Object)
is less than this then add an idle object. - period – the frequency to check the number of idle objects in a keyedPool, see
Timer.schedule(TimerTask, long, long)
.
Type parameters: Throws: - IllegalArgumentException –
when
keyedPool
, key
is
null
or when minIdle
is negative or
when period
isn't valid for Timer.schedule(TimerTask, long, long)
.
Returns: the TimerTask
that will periodically check the pools idle object count.
/**
* 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 period
* the frequency 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>, <code>key</code> is
* <code>null</code> or when <code>minIdle</code> is negative or
* when <code>period</code> isn't valid for
* {@link Timer#schedule(TimerTask, long, long)}.
*/
public static <K, V> TimerTask checkMinIdle(
final KeyedObjectPool<K, V> keyedPool, final K key,
final int minIdle, final long period)
throws IllegalArgumentException {
if (keyedPool == null) {
throw new IllegalArgumentException(MSG_NULL_KEYED_POOL);
}
if (key == null) {
throw new IllegalArgumentException(MSG_NULL_KEY);
}
if (minIdle < 0) {
throw new IllegalArgumentException(MSG_MIN_IDLE);
}
final TimerTask task = new KeyedObjectPoolMinIdleTimerTask<>(
keyedPool, key, minIdle);
getMinIdleTimer().schedule(task, 0L, period);
return task;
}
Periodically check the idle object count for each key in the
Collection
keys
in the keyedPool. At most one
idle object will be added per period.
Params: - keyedPool –
the keyedPool to check periodically.
- keys –
a collection of keys to check the idle object count.
- minIdle – if the
KeyedObjectPool.getNumIdle(Object)
is less than this then add an idle object. - period – the frequency to check the number of idle objects in a keyedPool, see
Timer.schedule(TimerTask, long, long)
.
Type parameters: Throws: - IllegalArgumentException –
when
keyedPool
, keys
, or any of the
values in the collection is null
or when
minIdle
is negative or when period
isn't valid for Timer.schedule(TimerTask, long, long)
.
See Also: Returns: a Map
of key and TimerTask
pairs that will periodically check the pools idle object count.
/**
* Periodically check the idle object count for each key in the
* <code>Collection</code> <code>keys</code> 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 period
* the frequency 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>, <code>keys</code>, or any of the
* values in the collection is <code>null</code> or when
* <code>minIdle</code> is negative or when <code>period</code>
* isn't valid for {@link Timer#schedule(TimerTask, long, long)}
* .
* @see #checkMinIdle(KeyedObjectPool, Object, int, long)
*/
public static <K, V> Map<K, TimerTask> checkMinIdle(
final KeyedObjectPool<K, V> keyedPool, final Collection<K> keys,
final int minIdle, final long period)
throws IllegalArgumentException {
if (keys == null) {
throw new IllegalArgumentException(MSG_NULL_KEYS);
}
final Map<K, TimerTask> tasks = new HashMap<>(keys.size());
final Iterator<K> iter = keys.iterator();
while (iter.hasNext()) {
final K key = iter.next();
final TimerTask task = checkMinIdle(keyedPool, key, minIdle, period);
tasks.put(key, task);
}
return tasks;
}
Params: - pool –
the pool to prefill.
- count –
the number of idle objects to add.
Type parameters: - <T> – the type of objects in the pool
Throws: - Exception – when
ObjectPool.addObject()
fails. - IllegalArgumentException –
when
pool
is null
.
/**
* Calls {@link ObjectPool#addObject()} on <code>pool</code> <code>count</code>
* 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</code> is <code>null</code>.
*/
public static <T> void prefill(final ObjectPool<T> pool, final int count)
throws Exception, IllegalArgumentException {
if (pool == null) {
throw new IllegalArgumentException(MSG_NULL_POOL);
}
for (int i = 0; i < count; i++) {
pool.addObject();
}
}
Params: - keyedPool –
the keyedPool to prefill.
- key –
the key to add objects for.
- count –
the number of idle objects to add for
key
.
Type parameters: Throws: - Exception – when
KeyedObjectPool.addObject(Object)
fails. - IllegalArgumentException –
when
keyedPool
or key
is
null
.
/**
* Calls {@link KeyedObjectPool#addObject(Object)} on <code>keyedPool</code> with
* <code>key</code> <code>count</code> 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</code>.
* @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> or <code>key</code> is
* <code>null</code>.
*/
public static <K, V> void prefill(final KeyedObjectPool<K, V> keyedPool,
final K key, final int count) throws Exception,
IllegalArgumentException {
if (keyedPool == null) {
throw new IllegalArgumentException(MSG_NULL_KEYED_POOL);
}
if (key == null) {
throw new IllegalArgumentException(MSG_NULL_KEY);
}
for (int i = 0; i < count; i++) {
keyedPool.addObject(key);
}
}
Calls KeyedObjectPool.addObject(Object)
on keyedPool
with each
key in keys
for count
number of times. This has the same effect as calling prefill(KeyedObjectPool<Object,Object>, Object, int)
for each key in the keys
collection.
Params: - keyedPool –
the keyedPool to prefill.
- keys –
Collection
of keys to add objects for. - count –
the number of idle objects to add for each
key
.
Type parameters: Throws: - Exception – when
KeyedObjectPool.addObject(Object)
fails. - IllegalArgumentException –
when
keyedPool
, keys
, or any value
in keys
is null
.
See Also:
/**
* Calls {@link KeyedObjectPool#addObject(Object)} on <code>keyedPool</code> with each
* key in <code>keys</code> for <code>count</code> number of times. This has
* the same effect as calling {@link #prefill(KeyedObjectPool, Object, int)}
* for each key in the <code>keys</code> 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</code>.
* @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>, <code>keys</code>, or any value
* in <code>keys</code> is <code>null</code>.
* @see #prefill(KeyedObjectPool, Object, int)
*/
public static <K, V> void prefill(final KeyedObjectPool<K, V> keyedPool,
final Collection<K> keys, final int count) throws Exception,
IllegalArgumentException {
if (keys == null) {
throw new IllegalArgumentException(MSG_NULL_KEYS);
}
final Iterator<K> iter = keys.iterator();
while (iter.hasNext()) {
prefill(keyedPool, iter.next(), count);
}
}
Returns a synchronized (thread-safe) ObjectPool backed by the specified
ObjectPool.
Note: 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 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.
Params: - pool –
the ObjectPool to be "wrapped" in a synchronized ObjectPool.
Type parameters: - <T> – the type of objects in the pool
Returns: a synchronized view of the specified ObjectPool.
/**
* 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 pool
* the ObjectPool to be "wrapped" in a synchronized ObjectPool.
* @param <T> the type of objects in the pool
* @return a synchronized view of the specified ObjectPool.
*/
public static <T> ObjectPool<T> synchronizedPool(final ObjectPool<T> pool) {
if (pool == null) {
throw new IllegalArgumentException(MSG_NULL_POOL);
}
/*
* assert !(pool instanceof GenericObjectPool) :
* "GenericObjectPool is already thread-safe"; assert !(pool instanceof
* SoftReferenceObjectPool) :
* "SoftReferenceObjectPool is already thread-safe"; assert !(pool
* instanceof StackObjectPool) :
* "StackObjectPool is already thread-safe"; assert
* !"org.apache.commons.pool.composite.CompositeObjectPool"
* .equals(pool.getClass().getName()) :
* "CompositeObjectPools are already thread-safe";
*/
return new SynchronizedObjectPool<>(pool);
}
Returns a synchronized (thread-safe) KeyedObjectPool backed by the
specified KeyedObjectPool.
Note: 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 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.
Params: - keyedPool –
the KeyedObjectPool to be "wrapped" in a synchronized
KeyedObjectPool.
Type parameters: Returns: a synchronized view of the specified KeyedObjectPool.
/**
* 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.
*/
public static <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";
*/
return new SynchronizedKeyedObjectPool<>(keyedPool);
}
Returns a synchronized (thread-safe) PooledObjectFactory backed by the
specified PooledObjectFactory.
Params: - factory –
the PooledObjectFactory to be "wrapped" in a synchronized
PooledObjectFactory.
Type parameters: - <T> – the type of objects in the pool
Returns: a synchronized view of the specified PooledObjectFactory.
/**
* 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.
*/
public static <T> PooledObjectFactory<T> synchronizedPooledFactory(
final PooledObjectFactory<T> factory) {
return new SynchronizedPooledObjectFactory<>(factory);
}
Returns a synchronized (thread-safe) KeyedPooledObjectFactory backed by
the specified KeyedPoolableObjectFactory.
Params: - keyedFactory –
the KeyedPooledObjectFactory to be "wrapped" in a
synchronized KeyedPooledObjectFactory.
Type parameters: Returns: a synchronized view of the specified KeyedPooledObjectFactory.
/**
* Returns a synchronized (thread-safe) KeyedPooledObjectFactory backed by
* the specified KeyedPoolableObjectFactory.
*
* @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.
*/
public static <K, V> KeyedPooledObjectFactory<K, V> synchronizedKeyedPooledFactory(
final KeyedPooledObjectFactory<K, V> keyedFactory) {
return new SynchronizedKeyedPooledObjectFactory<>(keyedFactory);
}
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.
Params: - pool –
the ObjectPool to be decorated so it shrinks its idle count
when possible.
Type parameters: - <T> – the type of objects in the pool
See Also: Returns: a pool that adaptively decreases its size when idle objects are
no longer needed.
/**
* 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
* @return a pool that adaptively decreases its size when idle objects are
* no longer needed.
* @see #erodingPool(ObjectPool, float)
*/
public static <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.
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.
Params: - pool –
the ObjectPool to be decorated so it shrinks its idle count
when possible.
- 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.
Type parameters: - <T> – the type of objects in the pool
See Also: Returns: a pool that adaptively decreases its size when idle objects are
no longer needed.
/**
* 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
* @return a pool that adaptively decreases its size when idle objects are
* no longer needed.
* @see #erodingPool(ObjectPool)
*/
public static <T> ObjectPool<T> erodingPool(final ObjectPool<T> pool,
final float factor) {
if (pool == null) {
throw new IllegalArgumentException(MSG_NULL_POOL);
}
if (factor <= 0f) {
throw new IllegalArgumentException(MSG_FACTOR_NEGATIVE);
}
return new ErodingObjectPool<>(pool, 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.
Params: - keyedPool –
the KeyedObjectPool to be decorated so it shrinks its idle
count when possible.
Type parameters: See Also: Returns: a pool that adaptively decreases its size when idle objects are
no longer needed.
/**
* 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
* @return a pool that adaptively decreases its size when idle objects are
* no longer needed.
* @see #erodingPool(KeyedObjectPool, float)
* @see #erodingPool(KeyedObjectPool, float, boolean)
*/
public static <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.
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.
Params: - keyedPool –
the KeyedObjectPool to be decorated so it shrinks its idle
count when possible.
- 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.
Type parameters: See Also: Returns: a pool that adaptively decreases its size when idle objects are
no longer needed.
/**
* 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
* @return a pool that adaptively decreases its size when idle objects are
* no longer needed.
* @see #erodingPool(KeyedObjectPool, float, boolean)
*/
public static <K, V> KeyedObjectPool<K, V> erodingPool(
final KeyedObjectPool<K, V> keyedPool, final float 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.
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.
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.
Params: - keyedPool –
the KeyedObjectPool to be decorated so it shrinks its idle
count when possible.
- 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.
- perKey –
when true, each key is treated independently.
Type parameters: See Also: Returns: a pool that adaptively decreases its size when idle objects are
no longer needed.
/**
* 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
* @return a pool that adaptively decreases its size when idle objects are
* no longer needed.
* @see #erodingPool(KeyedObjectPool)
* @see #erodingPool(KeyedObjectPool, float)
*/
public static <K, V> KeyedObjectPool<K, V> erodingPool(
final KeyedObjectPool<K, V> keyedPool, final float factor,
final boolean perKey) {
if (keyedPool == null) {
throw new IllegalArgumentException(MSG_NULL_KEYED_POOL);
}
if (factor <= 0f) {
throw new IllegalArgumentException(MSG_FACTOR_NEGATIVE);
}
if (perKey) {
return new ErodingPerKeyKeyedObjectPool<>(keyedPool, factor);
}
return new ErodingKeyedObjectPool<>(keyedPool, factor);
}
Gets the Timer
for checking keyedPool's idle count.
Returns: the Timer
for checking keyedPool's idle count.
/**
* Gets the <code>Timer</code> for checking keyedPool's idle count.
*
* @return the {@link Timer} for checking keyedPool's idle count.
*/
private static Timer getMinIdleTimer() {
return TimerHolder.MIN_IDLE_TIMER;
}
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.
Type parameters: - <T> – type of objects in the pool
/**
* 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
*/
private static final class ObjectPoolMinIdleTimerTask<T> extends TimerTask {
Minimum number of idle instances. Not the same as pool.getMinIdle(). /** Minimum number of idle instances. Not the same as pool.getMinIdle(). */
private final int minIdle;
Object pool /** Object pool */
private final ObjectPool<T> pool;
Create a new ObjectPoolMinIdleTimerTask for the given pool with the
given minIdle setting.
Params: - pool –
object pool
- minIdle –
number of idle instances to maintain
Throws: - IllegalArgumentException –
if the pool is null
/**
* Create 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, final int minIdle)
throws IllegalArgumentException {
if (pool == null) {
throw new IllegalArgumentException(MSG_NULL_POOL);
}
this.pool = pool;
this.minIdle = minIdle;
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
@Override
public void run() {
boolean success = false;
try {
if (pool.getNumIdle() < minIdle) {
pool.addObject();
}
success = true;
} catch (final Exception e) {
cancel();
} finally {
// detect other types of Throwable and cancel this Timer
if (!success) {
cancel();
}
}
}
{@inheritDoc}
/**
* {@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();
}
}
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.
Type parameters: - <K> – object pool key type
- <V> – object pool value type
/**
* 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
*/
private static final class KeyedObjectPoolMinIdleTimerTask<K, V> extends
TimerTask {
Minimum number of idle instances. Not the same as pool.getMinIdle(). /** Minimum number of idle instances. Not the same as pool.getMinIdle(). */
private final int minIdle;
Key to ensure minIdle for /** Key to ensure minIdle for */
private final K key;
Keyed object pool /** Keyed object pool */
private final KeyedObjectPool<K, V> keyedPool;
Creates a new KeyedObjecPoolMinIdleTimerTask.
Params: - keyedPool –
keyed object pool
- key –
key to ensure minimum number of idle instances
- minIdle –
minimum number of idle instances
Throws: - IllegalArgumentException –
if the key is null
/**
* 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, final int minIdle) throws IllegalArgumentException {
if (keyedPool == null) {
throw new IllegalArgumentException(
MSG_NULL_KEYED_POOL);
}
this.keyedPool = keyedPool;
this.key = key;
this.minIdle = minIdle;
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
@Override
public void run() {
boolean success = false;
try {
if (keyedPool.getNumIdle(key) < minIdle) {
keyedPool.addObject(key);
}
success = true;
} catch (final Exception e) {
cancel();
} finally {
// detect other types of Throwable and cancel this Timer
if (!success) {
cancel();
}
}
}
{@inheritDoc}
/**
* {@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();
}
}
A synchronized (thread-safe) ObjectPool backed by the specified
ObjectPool.
Note: 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 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.
Type parameters: - <T> – type of objects in the pool
/**
* 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
*/
private static final class SynchronizedObjectPool<T> implements ObjectPool<T> {
Object whose monitor is used to synchronize methods on the wrapped
pool.
/**
* Object whose monitor is used to synchronize methods on the wrapped
* pool.
*/
private final ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock();
the underlying object pool /** the underlying object pool */
private final ObjectPool<T> pool;
Creates a new SynchronizedObjectPool wrapping the given pool.
Params: - pool –
the ObjectPool to be "wrapped" in a synchronized
ObjectPool.
Throws: - IllegalArgumentException –
if the pool is null
/**
* 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) {
throw new IllegalArgumentException(MSG_NULL_POOL);
}
this.pool = pool;
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
@Override
public T borrowObject() throws Exception, NoSuchElementException,
IllegalStateException {
final WriteLock writeLock = readWriteLock.writeLock();
writeLock.lock();
try {
return pool.borrowObject();
} finally {
writeLock.unlock();
}
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
@Override
public void returnObject(final T obj) {
final WriteLock writeLock = readWriteLock.writeLock();
writeLock.lock();
try {
pool.returnObject(obj);
} catch (final Exception e) {
// swallowed as of Pool 2
} finally {
writeLock.unlock();
}
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
@Override
public void invalidateObject(final T obj) {
final WriteLock writeLock = readWriteLock.writeLock();
writeLock.lock();
try {
pool.invalidateObject(obj);
} catch (final Exception e) {
// swallowed as of Pool 2
} finally {
writeLock.unlock();
}
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
@Override
public void addObject() throws Exception, IllegalStateException,
UnsupportedOperationException {
final WriteLock writeLock = readWriteLock.writeLock();
writeLock.lock();
try {
pool.addObject();
} finally {
writeLock.unlock();
}
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
@Override
public int getNumIdle() {
final ReadLock readLock = readWriteLock.readLock();
readLock.lock();
try {
return pool.getNumIdle();
} finally {
readLock.unlock();
}
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
@Override
public int getNumActive() {
final ReadLock readLock = readWriteLock.readLock();
readLock.lock();
try {
return pool.getNumActive();
} finally {
readLock.unlock();
}
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
@Override
public void clear() throws Exception, UnsupportedOperationException {
final WriteLock writeLock = readWriteLock.writeLock();
writeLock.lock();
try {
pool.clear();
} finally {
writeLock.unlock();
}
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
@Override
public void close() {
final WriteLock writeLock = readWriteLock.writeLock();
writeLock.lock();
try {
pool.close();
} catch (final Exception e) {
// swallowed as of Pool 2
} finally {
writeLock.unlock();
}
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
@Override
public String toString() {
final StringBuilder sb = new StringBuilder();
sb.append("SynchronizedObjectPool");
sb.append("{pool=").append(pool);
sb.append('}');
return sb.toString();
}
}
A synchronized (thread-safe) KeyedObjectPool backed by the specified
KeyedObjectPool.
Note: 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 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.
Type parameters:
/**
* 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
*/
private static final class SynchronizedKeyedObjectPool<K, V> implements
KeyedObjectPool<K, V> {
Object whose monitor is used to synchronize methods on the wrapped
pool.
/**
* Object whose monitor is used to synchronize methods on the wrapped
* pool.
*/
private final ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock();
Underlying object pool /** Underlying object pool */
private final KeyedObjectPool<K, V> keyedPool;
Creates a new SynchronizedKeyedObjectPool wrapping the given pool
Params: - keyedPool –
KeyedObjectPool to wrap
Throws: - IllegalArgumentException –
if keyedPool is null
/**
* 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) {
throw new IllegalArgumentException(
MSG_NULL_KEYED_POOL);
}
this.keyedPool = keyedPool;
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
@Override
public V borrowObject(final K key) throws Exception,
NoSuchElementException, IllegalStateException {
final WriteLock writeLock = readWriteLock.writeLock();
writeLock.lock();
try {
return keyedPool.borrowObject(key);
} finally {
writeLock.unlock();
}
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
@Override
public void returnObject(final K key, final V obj) {
final WriteLock writeLock = readWriteLock.writeLock();
writeLock.lock();
try {
keyedPool.returnObject(key, obj);
} catch (final Exception e) {
// swallowed
} finally {
writeLock.unlock();
}
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
@Override
public void invalidateObject(final K key, final V obj) {
final WriteLock writeLock = readWriteLock.writeLock();
writeLock.lock();
try {
keyedPool.invalidateObject(key, obj);
} catch (final Exception e) {
// swallowed as of Pool 2
} finally {
writeLock.unlock();
}
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
@Override
public void addObject(final K key) throws Exception,
IllegalStateException, UnsupportedOperationException {
final WriteLock writeLock = readWriteLock.writeLock();
writeLock.lock();
try {
keyedPool.addObject(key);
} finally {
writeLock.unlock();
}
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
@Override
public int getNumIdle(final K key) {
final ReadLock readLock = readWriteLock.readLock();
readLock.lock();
try {
return keyedPool.getNumIdle(key);
} finally {
readLock.unlock();
}
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
@Override
public int getNumActive(final K key) {
final ReadLock readLock = readWriteLock.readLock();
readLock.lock();
try {
return keyedPool.getNumActive(key);
} finally {
readLock.unlock();
}
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
@Override
public int getNumIdle() {
final ReadLock readLock = readWriteLock.readLock();
readLock.lock();
try {
return keyedPool.getNumIdle();
} finally {
readLock.unlock();
}
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
@Override
public int getNumActive() {
final ReadLock readLock = readWriteLock.readLock();
readLock.lock();
try {
return keyedPool.getNumActive();
} finally {
readLock.unlock();
}
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
@Override
public void clear() throws Exception, UnsupportedOperationException {
final WriteLock writeLock = readWriteLock.writeLock();
writeLock.lock();
try {
keyedPool.clear();
} finally {
writeLock.unlock();
}
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
@Override
public void clear(final K key) throws Exception,
UnsupportedOperationException {
final WriteLock writeLock = readWriteLock.writeLock();
writeLock.lock();
try {
keyedPool.clear(key);
} finally {
writeLock.unlock();
}
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
@Override
public void close() {
final WriteLock writeLock = readWriteLock.writeLock();
writeLock.lock();
try {
keyedPool.close();
} catch (final Exception e) {
// swallowed as of Pool 2
} finally {
writeLock.unlock();
}
}
{@inheritDoc}
/**
* {@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 PooledObjectFactory that wraps a
PooledObjectFactory and synchronizes access to the wrapped factory
methods.
Note: This should not be used on pool implementations that already
provide proper synchronization such as the pools provided in the Commons
Pool library.
Type parameters: - <T> – pooled object factory type
/**
* 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
*/
private static final class SynchronizedPooledObjectFactory<T> implements
PooledObjectFactory<T> {
Synchronization lock /** Synchronization lock */
private final WriteLock writeLock = new ReentrantReadWriteLock().writeLock();
Wrapped factory /** Wrapped factory */
private final PooledObjectFactory<T> factory;
Creates a SynchronizedPoolableObjectFactory wrapping the given
factory.
Params: - factory –
underlying factory to wrap
Throws: - IllegalArgumentException –
if the factory is null
/**
* 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) {
throw new IllegalArgumentException("factory must not be null.");
}
this.factory = factory;
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
@Override
public PooledObject<T> makeObject() throws Exception {
writeLock.lock();
try {
return factory.makeObject();
} finally {
writeLock.unlock();
}
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
@Override
public void destroyObject(final PooledObject<T> p) throws Exception {
writeLock.lock();
try {
factory.destroyObject(p);
} finally {
writeLock.unlock();
}
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
@Override
public boolean validateObject(final PooledObject<T> p) {
writeLock.lock();
try {
return factory.validateObject(p);
} finally {
writeLock.unlock();
}
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
@Override
public void activateObject(final PooledObject<T> p) throws Exception {
writeLock.lock();
try {
factory.activateObject(p);
} finally {
writeLock.unlock();
}
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
@Override
public void passivateObject(final PooledObject<T> p) throws Exception {
writeLock.lock();
try {
factory.passivateObject(p);
} finally {
writeLock.unlock();
}
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
@Override
public String toString() {
final StringBuilder sb = new StringBuilder();
sb.append("SynchronizedPoolableObjectFactory");
sb.append("{factory=").append(factory);
sb.append('}');
return sb.toString();
}
}
A fully synchronized KeyedPooledObjectFactory that wraps a
KeyedPooledObjectFactory and synchronizes access to the wrapped factory
methods.
Note: This should not be used on pool implementations that already
provide proper synchronization such as the pools provided in the Commons
Pool library.
Type parameters: - <K> – pooled object factory key type
- <V> – pooled object factory key value
/**
* 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 key value
*/
private static final class SynchronizedKeyedPooledObjectFactory<K, V>
implements KeyedPooledObjectFactory<K, V> {
Synchronization lock /** Synchronization lock */
private final WriteLock writeLock = new ReentrantReadWriteLock().writeLock();
Wrapped factory /** Wrapped factory */
private final KeyedPooledObjectFactory<K, V> keyedFactory;
Creates a SynchronizedKeyedPoolableObjectFactory wrapping the given
factory.
Params: - keyedFactory –
underlying factory to wrap
Throws: - IllegalArgumentException –
if the factory is null
/**
* Creates a SynchronizedKeyedPoolableObjectFactory 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) {
throw new IllegalArgumentException(
"keyedFactory must not be null.");
}
this.keyedFactory = keyedFactory;
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
@Override
public PooledObject<V> makeObject(final K key) throws Exception {
writeLock.lock();
try {
return keyedFactory.makeObject(key);
} finally {
writeLock.unlock();
}
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
@Override
public void destroyObject(final K key, final PooledObject<V> p) throws Exception {
writeLock.lock();
try {
keyedFactory.destroyObject(key, p);
} finally {
writeLock.unlock();
}
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
@Override
public boolean validateObject(final K key, final PooledObject<V> p) {
writeLock.lock();
try {
return keyedFactory.validateObject(key, p);
} finally {
writeLock.unlock();
}
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
@Override
public void activateObject(final K key, final PooledObject<V> p) throws Exception {
writeLock.lock();
try {
keyedFactory.activateObject(key, p);
} finally {
writeLock.unlock();
}
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
@Override
public void passivateObject(final K key, final PooledObject<V> p) throws Exception {
writeLock.lock();
try {
keyedFactory.passivateObject(key, p);
} finally {
writeLock.unlock();
}
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
@Override
public String toString() {
final StringBuilder sb = new StringBuilder();
sb.append("SynchronizedKeyedPoolableObjectFactory");
sb.append("{keyedFactory=").append(keyedFactory);
sb.append('}');
return sb.toString();
}
}
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.
/**
* 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.
*/
private static final class ErodingFactor {
Determines frequency of "erosion" events /** Determines frequency of "erosion" events */
private final float factor;
Time of next shrink event /** Time of next shrink event */
private transient volatile long nextShrink;
High water mark - largest numIdle encountered /** High water mark - largest numIdle encountered */
private transient volatile int idleHighWaterMark;
Creates a new ErodingFactor with the given erosion factor.
Params: - factor –
erosion factor
/**
* Creates a new ErodingFactor with the given erosion factor.
*
* @param factor
* erosion factor
*/
public ErodingFactor(final float factor) {
this.factor = factor;
nextShrink = System.currentTimeMillis() + (long) (900000 * factor); // now
// +
// 15
// min
// *
// factor
idleHighWaterMark = 1;
}
Updates internal state using the supplied time and numIdle.
Params: - now –
current time
- numIdle –
number of idle elements in the pool
/**
* Updates internal state using the supplied time and numIdle.
*
* @param now
* current time
* @param numIdle
* number of idle elements in the pool
*/
public void update(final long now, final int numIdle) {
final int idle = Math.max(0, numIdle);
idleHighWaterMark = Math.max(idle, idleHighWaterMark);
final float maxInterval = 15f;
final float minutes = maxInterval +
((1f - maxInterval) / idleHighWaterMark) * idle;
nextShrink = now + (long) (minutes * 60000f * factor);
}
Returns the time of the next erosion event.
Returns: next shrink time
/**
* Returns the time of the next erosion event.
*
* @return next shrink time
*/
public long getNextShrink() {
return nextShrink;
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
@Override
public String toString() {
return "ErodingFactor{" + "factor=" + factor +
", idleHighWaterMark=" + idleHighWaterMark + '}';
}
}
Decorates an 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. Type parameters: - <T> – type of objects in the pool
/**
* 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
*/
private static class ErodingObjectPool<T> implements ObjectPool<T> {
Underlying object pool /** Underlying object pool */
private final ObjectPool<T> pool;
Erosion factor /** Erosion factor */
private final ErodingFactor factor;
Creates an ErodingObjectPool wrapping the given pool using the
specified erosion factor.
Params: - pool –
underlying pool
- factor –
erosion factor - determines the frequency of erosion
events
See Also:
/**
* 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
*/
public ErodingObjectPool(final ObjectPool<T> pool, final float factor) {
this.pool = pool;
this.factor = new ErodingFactor(factor);
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
@Override
public T borrowObject() throws Exception, NoSuchElementException,
IllegalStateException {
return pool.borrowObject();
}
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 and more than the erosion
factor
-determined time has elapsed since the last returnObject activation. Params: - obj –
object to return or invalidate
See Also:
/**
* 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 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
public void returnObject(final T obj) {
boolean discard = false;
final long now = System.currentTimeMillis();
synchronized (pool) {
if (factor.getNextShrink() < now) { // XXX: Pool 3: move test
// out of sync block
final int numIdle = pool.getNumIdle();
if (numIdle > 0) {
discard = true;
}
factor.update(now, numIdle);
}
}
try {
if (discard) {
pool.invalidateObject(obj);
} else {
pool.returnObject(obj);
}
} catch (final Exception e) {
// swallowed
}
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
@Override
public void invalidateObject(final T obj) {
try {
pool.invalidateObject(obj);
} catch (final Exception e) {
// swallowed
}
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
@Override
public void addObject() throws Exception, IllegalStateException,
UnsupportedOperationException {
pool.addObject();
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
@Override
public int getNumIdle() {
return pool.getNumIdle();
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
@Override
public int getNumActive() {
return pool.getNumActive();
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
@Override
public void clear() throws Exception, UnsupportedOperationException {
pool.clear();
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
@Override
public void close() {
try {
pool.close();
} catch (final Exception e) {
// swallowed
}
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
@Override
public String toString() {
return "ErodingObjectPool{" + "factor=" + factor + ", pool=" +
pool + '}';
}
}
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.
Type parameters: - <K> – object pool key type
- <V> – object pool value type
/**
* 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
*/
private static class ErodingKeyedObjectPool<K, V> implements
KeyedObjectPool<K, V> {
Underlying pool /** Underlying pool */
private final KeyedObjectPool<K, V> keyedPool;
Erosion factor /** Erosion factor */
private final ErodingFactor erodingFactor;
Creates an ErodingObjectPool wrapping the given pool using the
specified erosion factor.
Params: - keyedPool –
underlying pool
- factor –
erosion factor - determines the frequency of erosion
events
See Also:
/**
* 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
*/
public ErodingKeyedObjectPool(final KeyedObjectPool<K, V> keyedPool,
final float factor) {
this(keyedPool, new ErodingFactor(factor));
}
Creates an ErodingObjectPool wrapping the given pool using the
specified erosion factor.
Params: - keyedPool –
underlying pool - must not be null
- erodingFactor –
erosion factor - determines the frequency of erosion
events
See Also:
/**
* 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) {
throw new IllegalArgumentException(
MSG_NULL_KEYED_POOL);
}
this.keyedPool = keyedPool;
this.erodingFactor = erodingFactor;
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
@Override
public V borrowObject(final K key) throws Exception,
NoSuchElementException, IllegalStateException {
return keyedPool.borrowObject(key);
}
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 erosion factor
time has elapsed since the last returnObject activation. Params: - obj –
object to return or invalidate
- key –
key
See Also:
/**
* 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
public void returnObject(final K key, final V obj) throws Exception {
boolean discard = false;
final long now = System.currentTimeMillis();
final ErodingFactor factor = getErodingFactor(key);
synchronized (keyedPool) {
if (factor.getNextShrink() < now) {
final int numIdle = getNumIdle(key);
if (numIdle > 0) {
discard = true;
}
factor.update(now, numIdle);
}
}
try {
if (discard) {
keyedPool.invalidateObject(key, obj);
} else {
keyedPool.returnObject(key, obj);
}
} catch (final Exception e) {
// swallowed
}
}
Returns the eroding factor for the given key
Params: - key –
key
Returns: eroding factor for the given keyed pool
/**
* Returns 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;
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
@Override
public void invalidateObject(final K key, final V obj) {
try {
keyedPool.invalidateObject(key, obj);
} catch (final Exception e) {
// swallowed
}
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
@Override
public void addObject(final K key) throws Exception,
IllegalStateException, UnsupportedOperationException {
keyedPool.addObject(key);
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
@Override
public int getNumIdle() {
return keyedPool.getNumIdle();
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
@Override
public int getNumIdle(final K key) {
return keyedPool.getNumIdle(key);
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
@Override
public int getNumActive() {
return keyedPool.getNumActive();
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
@Override
public int getNumActive(final K key) {
return keyedPool.getNumActive(key);
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
@Override
public void clear() throws Exception, UnsupportedOperationException {
keyedPool.clear();
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
@Override
public void clear(final K key) throws Exception,
UnsupportedOperationException {
keyedPool.clear(key);
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
@Override
public void close() {
try {
keyedPool.close();
} catch (final Exception e) {
// swallowed
}
}
Returns the underlying pool
Returns: the keyed pool that this ErodingKeyedObjectPool wraps
/**
* Returns the underlying pool
*
* @return the keyed pool that this ErodingKeyedObjectPool wraps
*/
protected KeyedObjectPool<K, V> getKeyedPool() {
return keyedPool;
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
@Override
public String toString() {
return "ErodingKeyedObjectPool{" + "factor=" +
erodingFactor + ", keyedPool=" + keyedPool + '}';
}
}
Extends ErodingKeyedObjectPool to allow erosion to take place on a
per-key basis. Timing of erosion events is tracked separately for
separate keyed pools.
Type parameters: - <K> – object pool key type
- <V> – object pool value type
/**
* 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
*/
private static final class ErodingPerKeyKeyedObjectPool<K, V> extends
ErodingKeyedObjectPool<K, V> {
Erosion factor - same for all pools /** Erosion factor - same for all pools */
private final float factor;
Map of ErodingFactor instances keyed on pool keys /** Map of ErodingFactor instances keyed on pool keys */
private final Map<K, ErodingFactor> factors = Collections.synchronizedMap(new HashMap<K, ErodingFactor>());
Creates a new ErordingPerKeyKeyedObjectPool decorating the given keyed
pool with the specified erosion factor.
Params: - keyedPool –
underlying keyed pool
- factor –
erosion factor
/**
* Creates a new ErordingPerKeyKeyedObjectPool decorating the given keyed
* pool with the specified erosion factor.
*
* @param keyedPool
* underlying keyed pool
* @param factor
* erosion factor
*/
public ErodingPerKeyKeyedObjectPool(
final KeyedObjectPool<K, V> keyedPool, final float factor) {
super(keyedPool, null);
this.factor = factor;
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
@Override
protected ErodingFactor getErodingFactor(final K key) {
ErodingFactor eFactor = factors.get(key);
// this may result in two ErodingFactors being created for a key
// since they are small and cheap this is okay.
if (eFactor == null) {
eFactor = new ErodingFactor(this.factor);
factors.put(key, eFactor);
}
return eFactor;
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
@Override
public String toString() {
return "ErodingPerKeyKeyedObjectPool{" + "factor=" + factor +
", keyedPool=" + getKeyedPool() + '}';
}
}
}