commons-pool2中GenericObjectPoolConfig的maxTotal、maxIdle、minIdle屬性理解

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中的idleSoftEvictTimeidleEvictTime的默認值是在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;

所以IdleSoftEvictTimeIdleEvictTime的默認值分別是-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);
        }
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章