pool(四)——EvictionTimer

来源:互联网 发布:mac 穿越火线下载安装 编辑:程序博客网 时间:2024/05/21 10:56

1.BaseGenericObjectPool的startEvictor

/**     * <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);            }        }    }
这里会用EvictionTimer去执行Evictor这个任务。

2.EvictionTimer

对上一篇说的Timer进行了包装

/**     * Add the specified eviction task to the timer. Tasks that are added with a     * call to this method *must* call {@link #cancel(TimerTask)} to cancel the     * task to prevent memory and/or thread leaks in application server     * environments.     * @param task      Task to be scheduled     * @param delay     Delay in milliseconds before task is executed     * @param period    Time in milliseconds between executions     */    static synchronized void schedule(TimerTask task, long delay, long period) {        if (null == _timer) {            // Force the new Timer thread to be created with a context class            // loader set to the class loader that loaded this library            ClassLoader ccl = AccessController.doPrivileged(                    new PrivilegedGetTccl());            try {                AccessController.doPrivileged(new PrivilegedSetTccl(                        EvictionTimer.class.getClassLoader()));                _timer = new Timer("commons-pool-EvictionTimer", true);            } finally {                AccessController.doPrivileged(new PrivilegedSetTccl(ccl));            }        }        _usageCount++;        _timer.schedule(task, delay, period);    }

3.Evictor

/**     * The idle object evictor {@link TimerTask}.     *     * @see GenericKeyedObjectPool#setTimeBetweenEvictionRunsMillis     */    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 {                // Set the class loader for the factory                Thread.currentThread().setContextClassLoader(                        factoryClassLoader);                // 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.                try {                    ensureMinIdle();                } catch (Exception e) {                    swallowException(e);                }            } finally {                // Restore the previous CCL                Thread.currentThread().setContextClassLoader(savedClassLoader);            }        }    }
该类是TimerTask的子类,run方法有两个主要功能,evict和ensureMinIdle,一个是清除对象池中过期的对象,一个是保证对象池中始终有个数为minIdle个对象。

4.evict方法

该方法中使用了EvictionPolicy来判断是对象池中的对象是否过期了。

默认的实现是:

public class DefaultEvictionPolicy<T> implements EvictionPolicy<T> {    @Override    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;    }}
如果结果是true,把该对象从对象池中移除,并计数加一。
/**     * Destroys a wrapped pooled object.     *     * @param toDestory The wrapped pooled object to destroy     *     * @throws Exception If the factory fails to destroy the pooled object     *                   cleanly     */    private void destroy(PooledObject<T> toDestory) throws Exception {        toDestory.invalidate();        idleObjects.remove(toDestory);        allObjects.remove(toDestory.getObject());        try {            factory.destroyObject(toDestory);        } finally {            destroyedCount.incrementAndGet();            createCount.decrementAndGet();        }    }

5.ensureMinIdle

/**     * Tries to ensure that {@code idleCount} idle instances exist in the pool.     * <p>     * Creates and adds idle instances until either {@link #getNumIdle()} reaches {@code idleCount}     * or the total number of objects (idle, checked out, or being created) reaches     * {@link #getMaxTotal()}. If {@code always} is false, no instances are created unless     * there are threads waiting to check out instances from the pool.     *     * @param idleCount the number of idle instances desired     * @param always true means create instances even if the pool has no threads waiting     * @throws Exception if the factory's makeObject throws     */    private void ensureIdle(int idleCount, boolean always) throws Exception {        if (idleCount < 1 || isClosed() || (!always && !idleObjects.hasTakeWaiters())) {            return;        }        while (idleObjects.size() < idleCount) {            PooledObject<T> p = create();            if (p == null) {                // Can't create objects, no reason to think another call to                // create will work. Give up.                break;            }            if (getLifo()) {                idleObjects.addFirst(p);            } else {                idleObjects.addLast(p);            }        }    }
保证 {@link GenericObjectPool#idleObjects} 对象的size和{@link GenericObjectPool#getMinIdle}一致。
但是如果 {@link GenericObjectPool#createCount} == {@link GenericObjectPool#maxTotal},{@link GenericObjectPool#create} 方法就无法继续创建对象了。

 /**     * Attempts to create a new wrapped pooled object.     * <p>     * If there are {@link #getMaxTotal()} objects already in circulation     * or in process of being created, this method returns null.     *     * @return The new wrapped pooled object     *     * @throws Exception if the object factory's {@code makeObject} fails     */    private PooledObject<T> create() throws Exception {        int localMaxTotal = getMaxTotal();        long newCreateCount = createCount.incrementAndGet();        if (localMaxTotal > -1 && newCreateCount > localMaxTotal ||                newCreateCount > Integer.MAX_VALUE) {            createCount.decrementAndGet();            return null;        }        final PooledObject<T> p;        try {            p = factory.makeObject();        } catch (Exception e) {            createCount.decrementAndGet();            throw e;        }        AbandonedConfig ac = this.abandonedConfig;        if (ac != null && ac.getLogAbandoned()) {            p.setLogAbandoned(true);        }        createdCount.incrementAndGet();        allObjects.put(p.getObject(), p);        return p;    }

0 0
原创粉丝点击