GenericObjectPoolConfig
GenericObjectPoolConfig
是在GenericObjectPool
構造的時候使用的,用來設置pool的maxTotal、maxIdle、minIdle等屬性。
maxTotal比較好理解,表示pool中對象最多能有多少。主要是在create
函數中創建對象時進行判斷
int localMaxTotal = getMaxTotal();
long newCreateCount = createCount.incrementAndGet();
if (localMaxTotal > -1 && newCreateCount > localMaxTotal ||
newCreateCount > Integer.MAX_VALUE) {
createCount.decrementAndGet();
return null;
}
maxIdle屬性是指pool中最多能保留多少個空閒對象。這個屬性主要是在returnObject
函數中使用的。在程序使用完相關的對象後,會調用returnObject函數將對象返回到pool中。但是如果當前maxIdleSave <= idleObjects.size()
,即當前pool中空閒對象的數量大於等於maxIdle時候,直接調用destroy
函數來銷燬對象
int maxIdleSave = getMaxIdle();
if (isClosed() || maxIdleSave > -1 && maxIdleSave <= idleObjects.size()) {
try {
destroy(p);
} catch (Exception e) {
swallowException(e);
}
}
minIdle屬性是指pool中最少有多少個空閒對象。該屬性主要是在evict
函數中調用。封裝成EvictionConfig
對象後,調用EvictionPolicy中的evict方法來判斷是否需要回收當前測試的對象。
public boolean evict(EvictionConfig config, PooledObject<T> underTest,
int idleCount) {
if ((config.getIdleSoftEvictTime() < underTest.getIdleTimeMillis() &&
config.getMinIdle() < idleCount) ||
config.getIdleEvictTime() < underTest.getIdleTimeMillis()) {
return true;
}
return false;
}
可以看出如果當前測試對象的空閒時間大於config中設置的idleSoftEvictTime並且pool中空閒對象的數量大於minIdle,那麼就會return true。然後就會回收銷燬該對象。
其中EvictionConfig中的idleSoftEvictTime
和idleEvictTime
的默認值是在BaseObjectPoolConfig
中定義的。
/**
* The default value for the {@code minEvictableIdleTimeMillis}
* configuration attribute.
* @see GenericObjectPool#getMinEvictableIdleTimeMillis()
* @see GenericKeyedObjectPool#getMinEvictableIdleTimeMillis()
*/
public static final long DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS =
1000L * 60L * 30L;
/**
* The default value for the {@code softMinEvictableIdleTimeMillis}
* configuration attribute.
* @see GenericObjectPool#getSoftMinEvictableIdleTimeMillis()
* @see GenericKeyedObjectPool#getSoftMinEvictableIdleTimeMillis()
*/
public static final long DEFAULT_SOFT_MIN_EVICTABLE_IDLE_TIME_MILLIS = -1;
所以IdleSoftEvictTime
和IdleEvictTime
的默認值分別是-1和半小時
evict函數是有一個定時任務定時去調用的。所以pool中一般會維持minIdle個閒置對象。所以如果當前pool中閒置對象的數量小於minIdle,pool並不會創建新的對象。minIdle只是用來回收對象的時候進行判斷。
class Evictor extends TimerTask {
/**
* Run pool maintenance. Evict objects qualifying for eviction and then
* ensure that the minimum number of idle instances are available.
* Since the Timer that invokes Evictors is shared for all Pools but
* pools may exist in different class loaders, the Evictor ensures that
* any actions taken are under the class loader of the factory
* associated with the pool.
*/
@Override
public void run() {
ClassLoader savedClassLoader =
Thread.currentThread().getContextClassLoader();
try {
...
// Evict from the pool
try {
evict();
} catch(Exception e) {
swallowException(e);
} catch(OutOfMemoryError oome) {
// Log problem but give evictor thread a chance to continue
// in case error is recoverable
oome.printStackTrace(System.err);
}
// Re-create idle instances.
...
} finally {
// Restore the previous CCL
Thread.currentThread().setContextClassLoader(savedClassLoader);
}
}
}
該定時器是在GenericObjectPool
的構造函數中調用的,調用間隔是由timeBetweenEvictionRunsMillis
參數控制的。timeBetweenEvictionRunsMillis
的默認值是-1L。這個時候定時器任務是不啓用的,所以不會去調用evict來回收對象。
/**
* <p>Starts the evictor with the given delay. If there is an evictor
* running when this method is called, it is stopped and replaced with a
* new evictor with the specified delay.</p>
*
* <p>This method needs to be final, since it is called from a constructor.
* See POOL-195.</p>
*
* @param delay time in milliseconds before start and between eviction runs
*/
final void startEvictor(long delay) {
synchronized (evictionLock) {
if (null != evictor) {
EvictionTimer.cancel(evictor);
evictor = null;
evictionIterator = null;
}
if (delay > 0) {
evictor = new Evictor();
EvictionTimer.schedule(evictor, delay, delay);
}
}
}