對象池common-pool2策略分析

上一篇:對象池common-pool2分析java

common-pool2策略ide

上一篇對象池common-pool2分析從三個主要的接口進行分析,這一篇將對源碼進行詳細的分析,力圖找出對象池的管理策略.從以前的分析能夠看出ObjectPool定義了對象池須要實現的功能,因此重點分析ObjectPool.this

GenericObjectPool:通常對象池spa

GenericKeyedObjectPool:能夠根據key分組的對象池.net

SoftReferenceObjectPool:軟引用對象池. 線程

GenericObjectPoolcode

public GenericObjectPool(PooledObjectFactory<T> factory,
        GenericObjectPoolConfig config) {

    super(config, ONAME_BASE, config.getJmxNamePrefix());

    if (factory == null) {
        jmxUnregister(); // tidy up
        throw new IllegalArgumentException("factory may not be null");
    }
    this.factory = factory;
    //根據給定的容量和策略建立空閒對象隊列,默認容量Integer.MAX_VALUE
    //fairness爲true時相似FIFO隊列
    idleObjects = new LinkedBlockingDeque<PooledObject<T>>(config.getFairness());
    //設置配置信息
    setConfig(config);
    //根據給定延遲啓動驅逐器
    startEvictor(getTimeBetweenEvictionRunsMillis());
}

BaseGenericObjectPool對象

final void startEvictor(long delay) {
    synchronized (evictionLock) {
        //若是evictor已經啓動則中止
        if (null != evictor) {
            EvictionTimer.cancel(evictor);
            evictor = null;
            evictionIterator = null;
        }
        //當delay即timeBetweenEvictionRunsMillis大於0時根據給定的delay啓動新的驅逐器
        if (delay > 0) {
            evictor = new Evictor();
            EvictionTimer.schedule(evictor, delay, delay);
        }
    }
}

BaseGenericObjectPool內部類Evictor
blog

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 {
            if (factoryClassLoader != null) {
                // Set the class loader for the factory
                ClassLoader cl = factoryClassLoader.get();
                if (cl == null) {
                    // The pool has been dereferenced and the class loader
                    // GC'd. Cancel this timer so the pool can be GC'd as
                    // well.
                    cancel();
                    return;
                }
                Thread.currentThread().setContextClassLoader(cl);
            }

            // Evict from the pool
            try {
                //調用public abstract void evict() throws Exception;此方法由子類實現.
                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);
        }
    }
}

GenericObjectPool的方法evict()接口

public void evict() throws Exception {
    assertOpen();//確保鏈接池是打開的

    if (idleObjects.size() > 0) {

        PooledObject<T> underTest = null;
        //獲取驅逐策略
        EvictionPolicy<T> evictionPolicy = getEvictionPolicy();

        synchronized (evictionLock) {
            //驅逐配置
            EvictionConfig evictionConfig = new EvictionConfig(
                    getMinEvictableIdleTimeMillis(),
                    getSoftMinEvictableIdleTimeMillis(),
                    getMinIdle());
            //空閒時檢查
            boolean testWhileIdle = getTestWhileIdle();
            //getNumTests()獲取檢測的數量
            for (int i = 0, m = getNumTests(); i < m; i++) {
                if (evictionIterator == null || !evictionIterator.hasNext()) {
                    if (getLifo()) {//鏈接池是不是後進先出
                        //返回倒序的迭代
                        evictionIterator = idleObjects.descendingIterator();
                    } else {
                        evictionIterator = idleObjects.iterator();
                    }
                }
                if (!evictionIterator.hasNext()) {
                    // Pool exhausted, nothing to do here
                    return;
                }

                try {
                    //獲取對象
                    underTest = evictionIterator.next();
                } catch (NoSuchElementException nsee) {
                    // Object was borrowed in another thread
                    // Don't count this as an eviction test so reduce i;
                    i--;
                    evictionIterator = null;
                    continue;
                }

                if (!underTest.startEvictionTest()) {
                    // Object was borrowed in another thread
                    // Don't count this as an eviction test so reduce i;
                    i--;
                    continue;
                }

                // User provided eviction policy could throw all sorts of
                // crazy exceptions. Protect against such an exception
                // killing the eviction thread.
                boolean evict;
                try {
                    //檢測對象池裏的空閒對象是否應該被驅逐
                    evict = evictionPolicy.evict(evictionConfig, underTest,
                            idleObjects.size());
                } catch (Throwable t) {
                    // Slightly convoluted as SwallowedExceptionListener
                    // uses Exception rather than Throwable
                    PoolUtils.checkRethrow(t);
                    swallowException(new Exception(t));
                    // Don't evict on error conditions
                    evict = false;
                }

                if (evict) {
                    destroy(underTest);//銷燬
                    destroyedByEvictorCount.incrementAndGet();
                } else {
                    if (testWhileIdle) {
                        boolean active = false;
                        try {
                            factory.activateObject(underTest);//激活
                            active = true;
                        } catch (Exception e) {
                            destroy(underTest);//激活異常則銷燬
                            destroyedByEvictorCount.incrementAndGet();
                        }
                        if (active) {//已經激活
                            if (!factory.validateObject(underTest)) {//驗證不經過則銷燬
                                destroy(underTest);
                                destroyedByEvictorCount.incrementAndGet();
                            } else {
                                try {
                                    factory.passivateObject(underTest);//鈍化
                                } catch (Exception e) {
                                    destroy(underTest);
                                    destroyedByEvictorCount.incrementAndGet();
                                }
                            }
                        }
                    }
                    if (!underTest.endEvictionTest(idleObjects)) {
                        // TODO - May need to add code here once additional
                        // states are used
                    }
                }
            }
        }
    }
    AbandonedConfig ac = this.abandonedConfig;
    if (ac != null && ac.getRemoveAbandonedOnMaintenance()) {
        removeAbandoned(ac);
    }
}

GenericKeyedObjectPool

GenericObjectPool相似,只是須要遍歷key,根據key獲取空閒對象.

SoftReferenceObjectPool

若是一個對象只具備軟引用,則內存空間足夠,垃圾回收器就不會回收它;若是內存空間不足了,就會回收這些對象的內存。SoftReferenceObjectPool沒有後臺驅逐線程,當內存不足時由虛擬機清除.

相關文章
相關標籤/搜索