zoukankan      html  css  js  c++  java
  • GenericObjectPool

    commons-pool2源码走读(四) 对象池实现GenericObjectPool

    版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
    本文链接:https://blog.csdn.net/qq447995687/article/details/80469790

    commons-pool2源码走读(四) 对象池实现GenericObjectPool<T>

    GenericObjectPool <T> 是一个可配置的ObjectPool实现。 
    当与适当的PooledObjectFactory组合使用时,GenericObjectPool为任意对象提供健壮的池功能。

    您可以选择性的配置池来检查和可能回收池中的空闲对象,并确保有最少数量的空闲对象可用。这是由一个“空闲对象回收”线程(即BaseGenericObjectPool <T> 的Evictor)执行的,线程是异步运行的。在配置这个可选特性时,应该谨慎使用。驱逐运行与客户端线程争用池中的对象,因此如果它们运行得太频繁,可能会导致性能问题。

    还可以配置池来检测和删除被泄漏的对象,比如一个从池中借出的对象,在超过removeAbandonedTimeout超时之前既不使用也不返回。移除泄漏的连接,可能发生在对象被借用时对象池已接近饱和,也可能是被回收线程检查出,或者两者都执行时。如果池对象实现了TrackedUse接口,那么其最后一次使用时间使取决于getLastUsed方法;否则,是由对象从池中借出的时间决定。

    实现注意:为了防止可能的死锁,已经采取了谨慎措施,以确保在同步块中不会发生对工厂方法的调用。这个类线程安全。

    1、接口继承、实现关系

    GenericObjectPool <T> 实现了ObjectPool<T> 具备对象池的功能,同时 继承了BaseGenericObjectPool<T> 的对于对象状态管理和回收等功能。 
    这里写图片描述

    2、构造函数

    构造函数通过GenericObjectPoolConfig 和PooledObjectFactory来进行参数的初始化和对象工厂类的引入。

        public GenericObjectPool(final PooledObjectFactory<T> factory,
                final GenericObjectPoolConfig config) {
            //父类BaseGenericObjectPool构造方法
            super(config, ONAME_BASE, config.getJmxNamePrefix());
    
            if (factory == null) {
                jmxUnregister(); // tidy up
                throw new IllegalArgumentException("factory may not be null");
            }
            this.factory = factory;
            //空闲对象队列,此队列非JDK而是自行实现的一个队列
            idleObjects = new LinkedBlockingDeque<>(config.getFairness());
            //覆盖BaseGenericObjectPool里面的配置参数
            setConfig(config);
            //初始化回收线程
            startEvictor(getTimeBetweenEvictionRunsMillis());
        }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    3、相关属性

        // --- 可配置的属性 -------------------------------------------------
        //最大空闲数量
        private volatile int maxIdle = GenericObjectPoolConfig.DEFAULT_MAX_IDLE;
        //最小空闲数量
        private volatile int minIdle = GenericObjectPoolConfig.DEFAULT_MIN_IDLE;
        //对象工厂
        private final PooledObjectFactory<T> factory;
    
        // --- 内部属性 -------------------------------------------------
    
        //池中所有的对象,只能是<=maxActive
        private final Map<IdentityWrapper<T>, PooledObject<T>> allObjects =
            new ConcurrentHashMap<>();
        //已创建对象总数(不包含已销毁的)
        private final AtomicLong createCount = new AtomicLong(0);
        //调用创建方法总线程数
        private long makeObjectCount = 0;
        //makeObjectCount 增长时并发锁
        private final Object makeObjectCountLock = new Object();
        //空闲对象队列
        private final LinkedBlockingDeque<PooledObject<T>> idleObjects;
    
        // JMX specific attributes
        private static final String ONAME_BASE =
            "org.apache.commons.pool2:type=GenericObjectPool,name=";
    
        //泄漏对象回收配置参数
        private volatile AbandonedConfig abandonedConfig = null;
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    4、 对象池方法实现

    • 借用对象 
      整个流程为,检查池是否关闭 –> 是否回收泄漏对象 –> 是否阻塞创建对象 –> 创建对象 –> 分配对象 –> 激活对象 –> 校验对象 –> 更改借用信息 –> 返回对象
       public T borrowObject(final long borrowMaxWaitMillis) throws Exception {
            //判断对象池是否关闭:BaseGenericObjectPool.closed==true
            assertOpen();
            //如果回收泄漏的参数配置不为空,并且removeAbandonedOnBorrow参数配置为true
            //并且Idle数量<2,Active数量>总数Total-3
            //在借用时进行回收泄漏连接(会影响性能)
            final AbandonedConfig ac = this.abandonedConfig;
            if (ac != null && ac.getRemoveAbandonedOnBorrow() &&
                    (getNumIdle() < 2) &&
                    (getNumActive() > getMaxTotal() - 3) ) {
                //回收泄漏对象
                removeAbandoned(ac);
            }
    
            PooledObject<T> p = null;
    
            //copy blockWhenExhausted 防止其它线程更改getBlockWhenExhausted值造成并发问题
            //借用对象时如果没有是否阻塞直到有对象产生
            final boolean blockWhenExhausted = getBlockWhenExhausted();
            //创建成功标识
            boolean create;
            //记录当前时间,用作记录借用操作总共花费的时间
            final long waitTime = System.currentTimeMillis();
            //当对象为空时一直获取
            while (p == null) {
                create = false;
                //从双端队列弹出第一个队首对象,为空返回null
                p = idleObjects.pollFirst();
                //如果为空则重新创建一个对象
                if (p == null) {
                    //创建对象
                    p = create();
                    //p==null可能对象池达到上限不能继续创建!
                    if (p != null) {
                        create = true;
                    }
                }
                //如果对象p还是为空则阻塞等待
                if (blockWhenExhausted) {
                    if (p == null) {
                        if (borrowMaxWaitMillis < 0) {
                            //没有超时时间则阻塞等待到有对象为止
                            p = idleObjects.takeFirst();
                        } else {
                            //有超时时间
                            p = idleObjects.pollFirst(borrowMaxWaitMillis,
                                    TimeUnit.MILLISECONDS);
                        }
                    }
                    //达到超时时间,还未取到对象,则抛出异常
                    if (p == null) {
                        throw new NoSuchElementException(
                                "Timeout waiting for idle object");
                    }
                } else {
                    //未取到对象,则抛出异常
                    if (p == null) {
                        throw new NoSuchElementException("Pool exhausted");
                    }
                }
                //调用PooledObject.allocate()方法分配对象
                //[具体实现请看](https://blog.csdn.net/qq447995687/article/details/80413227)
                if (!p.allocate()) {
                    p = null;
                }
                //分配成功
                if (p != null) {
                    try {
                        //激活对象,具体请看factory实现,对象重借出到归还整个流程经历的过程图
                        factory.activateObject(p);
                    } catch (final Exception e) {
                        try {
                            destroy(p);
                        } catch (final Exception e1) {
                            // Ignore - activation failure is more important
                        }
                        p = null;
                        if (create) {
                            final NoSuchElementException nsee = new NoSuchElementException(
                                    "Unable to activate object");
                            nsee.initCause(e);
                            throw nsee;
                        }
                    }
                    //对象创建成功,是否进行测试
                    if (p != null && (getTestOnBorrow() || create && getTestOnCreate())) {
                        boolean validate = false;
                        Throwable validationThrowable = null;
                        try {
                            //校验对象,具体请看factory实现,对象重借出到归还整个流程经历的过程图
                            validate = factory.validateObject(p);
                        } catch (final Throwable t) {
                            PoolUtils.checkRethrow(t);
                            validationThrowable = t;
                        }
                        //校验不通过则销毁对象
                        if (!validate) {
                            try {
                                destroy(p);
                                destroyedByBorrowValidationCount.incrementAndGet();
                            } catch (final Exception e) {
                                // Ignore - validation failure is more important
                            }
                            p = null;
                            if (create) {
                                final NoSuchElementException nsee = new NoSuchElementException(
                                        "Unable to validate object");
                                nsee.initCause(validationThrowable);
                                throw nsee;
                            }
                        }
                    }
                }
            }
            //更新对象借用状态
            updateStatsBorrow(p, System.currentTimeMillis() - waitTime);
    
            return p.getObject();
        }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119

    创建对象 
    当借用时,空闲对象为空,并且未达到池最大数量,则会调用该方法重新创建一个空闲对象

       private PooledObject<T> create() throws Exception {
            int localMaxTotal = getMaxTotal();
            // 如果最大数量为负数则设置为Integer的最大值
            if (localMaxTotal < 0) {
                localMaxTotal = Integer.MAX_VALUE;
            }
    
            // 是否创建成功的一个flag:
            // - TRUE:  调用工厂类成功创建一个对象
            // - FALSE: 返回空
            // - null:  重复创建
            Boolean create = null;
            while (create == null) {
                synchronized (makeObjectCountLock) {
                    //加上本次操作,总共创建个数
                    final long newCreateCount = createCount.incrementAndGet();
                    if (newCreateCount > localMaxTotal) {
                        //连接池容量已满,不能继续增长。在对最后一个对象的创建上,
                        //加入了设计较为精妙,需细细揣摩
                        createCount.decrementAndGet();
                        //调用创建对象方法线程数=0
                        if (makeObjectCount == 0) {
                            //容量已满并且没有线程调用makeObject()方法,
                            //表明没有任何可能性再继续创建对象,
                            //返回并等待归还的空闲对象
                            create = Boolean.FALSE;
                        } else {
                            //其它线程调用makeObject()方法在创建对象了。
                            //如果继续创建则可能超过对象池容量,不返回false,因为其它线程也在创建,
                            //但是是否能够创建成功是未知的,如果其它线程没能创建成功,
                            //则此线程可能会抢夺到继续创建的权利。
                            //释放锁,等待其它线程创建结束并唤醒该线程
                            makeObjectCountLock.wait();
                        }
                    } else {
                        // 对象池未满,从新创建一个对象
                        makeObjectCount++;
                        create = Boolean.TRUE;
                    }
                }
            }
            //对象池容量达到上限,返回null重新等待其它线程归还对象
            if (!create.booleanValue()) {
                return null;
            }
    
            final PooledObject<T> p;
            try {
                //创建一个新对象
                p = factory.makeObject();
            } catch (final Exception e) {
                createCount.decrementAndGet();
                throw e;
            } finally {
                //与上面wait()方法相呼应,
                //如果上面抛出了异常,唤醒其它线程争夺继续创建最后一个资源的权利
                synchronized (makeObjectCountLock) {
                    makeObjectCount--;
                    makeObjectCountLock.notifyAll();
                }
            }
            //设置泄漏参数,并加入调用堆栈
            final AbandonedConfig ac = this.abandonedConfig;
            if (ac != null && ac.getLogAbandoned()) {
                p.setLogAbandoned(true);
                // TODO: in 3.0, this can use the method defined on PooledObject
                if (p instanceof DefaultPooledObject<?>) {
                    ((DefaultPooledObject<T>) p).setRequireFullStackTrace(ac.getRequireFullStackTrace());
                }
            }
            //将创建总数增加,并将对象放入    allObjects  
            createdCount.incrementAndGet();
            allObjects.put(new IdentityWrapper<>(p.getObject()), p);
            return p;
        }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75

    回收泄漏对象

     private void removeAbandoned(final AbandonedConfig ac) {
            // Generate a list of abandoned objects to remove
            final long now = System.currentTimeMillis();
            //超时时间=当前时间-配置的超时时间,如果一个对象的上次借用时间在此时间之前,
            //说明上次借用后经过了removeAbandonedTimeout时间限制还未被归还过即可能是泄漏的对象
            final long timeout =
                    now - (ac.getRemoveAbandonedTimeout() * 1000L);
            //泄漏的,需要移除的对象列表
            final ArrayList<PooledObject<T>> remove = new ArrayList<>();
            final Iterator<PooledObject<T>> it = allObjects.values().iterator();
            //遍历池中对象依次判断是否需要移除
            while (it.hasNext()) {
                final PooledObject<T> pooledObject = it.next();
                synchronized (pooledObject) {
                    //如果对象的状态为已分配ALLOCATED ,并且已经超过泄漏定义时间则添加到需要移除队列进行统一移除
                    if (pooledObject.getState() == PooledObjectState.ALLOCATED &&
                            pooledObject.getLastUsedTime() <= timeout) {
                        pooledObject.markAbandoned();
                        remove.add(pooledObject);
                    }
                }
            }
    
            // 移除泄漏连接,如果配置了打印堆栈,则打印调用堆栈信息
            final Iterator<PooledObject<T>> itr = remove.iterator();
            while (itr.hasNext()) {
                final PooledObject<T> pooledObject = itr.next();
                if (ac.getLogAbandoned()) {
                    pooledObject.printStackTrace(ac.getLogWriter());
                }
                try {
                    //销毁对象
                    invalidateObject(pooledObject.getObject());
                } catch (final Exception e) {
                    e.printStackTrace();
                }
            }
        }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • invalidate对象
        public void invalidateObject(final T obj) throws Exception {
            //从所有对象中取出该对象,如果不存在则抛出异常
            final PooledObject<T> p = allObjects.get(new IdentityWrapper<>(obj));
            if (p == null) {
                if (isAbandonedConfig()) {
                    return;
                }
                throw new IllegalStateException(
                        "Invalidated object not currently part of this pool");
            }
            //如果对象不是无效状态PooledObjectState.INVALID,则销毁此对象
            synchronized (p) {
                if (p.getState() != PooledObjectState.INVALID) {
                    destroy(p);
                }
            }
            //
            ensureIdle(1, false);
        }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    销毁对象 
    销毁对象,并从池中移除,更新对象池已创建数量和总销毁数量

        private void destroy(final PooledObject<T> toDestroy) throws Exception {
            toDestroy.invalidate();
            idleObjects.remove(toDestroy);
            allObjects.remove(new IdentityWrapper<>(toDestroy.getObject()));
            try {
                factory.destroyObject(toDestroy);
            } finally {
                destroyedCount.incrementAndGet();
                createCount.decrementAndGet();
            }
        }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    确保最小空闲数量

        private void ensureIdle(final int idleCount, final boolean always) throws Exception {
            //!idleObjects.hasTakeWaiters()如果idleObjects队列还有线程等待获取对象则由最后一个
            //等待者确保最小空闲数量
            if (idleCount < 1 || isClosed() || (!always && !idleObjects.hasTakeWaiters())) {
                return;
            }
            //一直创建空闲对象知道空闲对象数量>总空闲数量阈值
            while (idleObjects.size() < idleCount) {
                final 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);
                }
            }
            //在此过程中如果连接池关闭则clear所有对象
            if (isClosed()) {
                clear();
            }
        }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 归还对象

    归还对象方法将适用完的对象从新放置回对象池中重复利用。其整个流程为:检查是否存在 –> 检查状态是否正确 –> 是否在归还时测试对象 –> 校验对象 –> 钝化(卸载)对象 –> 结束分配 –> 销毁/归还该对象 –> 更新连接池归还信息

        public void returnObject(final T obj) {
            final PooledObject<T> p = allObjects.get(new IdentityWrapper<>(obj));
    
            if (p == null) {
                //如果对象为空,并且没有配置泄漏参数则抛出异常,表明该对象不是连接池中的对象
                if (!isAbandonedConfig()) {
                    throw new IllegalStateException(
                            "Returned object not currently part of this pool");
                }
                //如果对象为空,表明该对象是abandoned并且已被销毁
                return; 
            }
    
            synchronized(p) {
                final PooledObjectState state = p.getState();
                //如果被归还的对象不是已分配状态,抛出异常
                if (state != PooledObjectState.ALLOCATED) {
                    throw new IllegalStateException(
                            "Object has already been returned to this pool or is invalid");
                }
                //更改状态为returning,避免在此过程中被标记为被遗弃。
                p.markReturning();
            }
    
            final long activeTime = p.getActiveTimeMillis();
            //是否在归还时测试该对象
            if (getTestOnReturn()) {
                //校验对象
                if (!factory.validateObject(p)) {
                    try {
                        //校验不通过则destroy对象
                        destroy(p);
                    } catch (final Exception e) {
                        swallowException(e);
                    }
                    try {
                        //确保最小空闲数量
                        ensureIdle(1, false);
                    } catch (final Exception e) {
                        swallowException(e);
                    }
                    //更新连接池归还信息BaseGenericObjectPool#returnedCount,activeTimes
                    updateStatsReturn(activeTime);
                    return;
                }
            }
            //校验通过
            try {
                //钝化(卸载)对象
                factory.passivateObject(p);
            } catch (final Exception e1) {
                swallowException(e1);
                try {
                    destroy(p);
                } catch (final Exception e) {
                    swallowException(e);
                }
                try {
                    ensureIdle(1, false);
                } catch (final Exception e) {
                    swallowException(e);
                }
                updateStatsReturn(activeTime);
                return;
            }
            //结束分配,如果对象为ALLOCATED或者RETURNING更改对象为空闲IDLE状态
            //具体看org.apache.commons.pool2.impl.DefaultPooledObject#deallocate方法
            if (!p.deallocate()) {
                throw new IllegalStateException(
                        "Object has already been returned to this pool or is invalid");
            }
    
            final int maxIdleSave = getMaxIdle();
            //如果对象池已经关闭或者空闲数量达到上限,则销毁该对象
            if (isClosed() || maxIdleSave > -1 && maxIdleSave <= idleObjects.size()) {
                try {
                    destroy(p);
                } catch (final Exception e) {
                    swallowException(e);
                }
            } else {
                //否则将归还的对象添加到空闲队列,连接池的最终目的:重用一个连接
                if (getLifo()) {
                    idleObjects.addFirst(p);
                } else {
                    idleObjects.addLast(p);
                }
                if (isClosed()) {
                    // Pool closed while object was being added to idle objects.
                    // Make sure the returned object is destroyed rather than left
                    // in the idle object pool (which would effectively be a leak)
                    clear();
                }
            }
            updateStatsReturn(activeTime);
        }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • clear连接池 
      依次销毁每个链接
        public void clear() {
            PooledObject<T> p = idleObjects.poll();
    
            while (p != null) {
                try {
                    destroy(p);
                } catch (final Exception e) {
                    swallowException(e);
                }
                p = idleObjects.poll();
            }
        }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 回收对象

    此方法实现了org.apache.commons.pool2.impl.BaseGenericObjectPool#evict 方法,用于回收线程回收空闲对象。 
    回收的整个流程为:判断池是否关闭及是否有空闲对象 –> 根据策略获得回收的条数 –> 判断对象状态开始进行回收 –> 根据回收策略EvictionPolicy判断是否能够回收 –> 如能回收则销毁对象 –> 不能回收则判断是否校验对象 –> 激活对象 –> 校验对象 –> 钝化对象 –> 结束回收更改对象状态 –> 回收泄漏连接

    public void evict() throws Exception {
            assertOpen();
    
            if (idleObjects.size() > 0) {
    
                PooledObject<T> underTest = null;
                final EvictionPolicy<T> evictionPolicy = getEvictionPolicy();
    
                synchronized (evictionLock) {
                    //回收参数
                    final EvictionConfig evictionConfig = new EvictionConfig(
                            getMinEvictableIdleTimeMillis(),
                            getSoftMinEvictableIdleTimeMillis(),
                            getMinIdle());
                    //是否在回收时测试对象
                    final boolean testWhileIdle = getTestWhileIdle();
                    //根据getNumTests()对部分对象进行回收测试
                    for (int i = 0, m = getNumTests(); i < m; i++) {
                        //evictionIterator是空闲对象的一个迭代器,可以想象为idleObjects.iterator()
                        if (evictionIterator == null || !evictionIterator.hasNext()) {
                            evictionIterator = new EvictionIterator(idleObjects);
                        }
                        if (!evictionIterator.hasNext()) {
                            // Pool exhausted, nothing to do here
                            return;
                        }
                        //多线程并发时,有可能上面检测到有对象,而另一个对象随后将其借出
                        try {
                            underTest = evictionIterator.next();
                        } catch (final NoSuchElementException nsee) {
                            // 对象被其它线程借出
                            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;
                        }
    
                        //根据回收策略判断对象是否能够被回收,单独分析
                        boolean evict;
                        try {
                            //根据回收策略判断对象是否能够被回收
                            evict = evictionPolicy.evict(evictionConfig, underTest,
                                    idleObjects.size());
                        } catch (final 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 (final Exception e) {
                                    destroy(underTest);
                                    destroyedByEvictorCount.incrementAndGet();
                                }
                                if (active) {
                                    //激活成功进行校验
                                    if (!factory.validateObject(underTest)) {
                                        //校验不通过则销毁对象
                                        destroy(underTest);
                                        destroyedByEvictorCount.incrementAndGet();
                                    } else {
                                        try {
                                            //校验通过则重新将对象钝化(卸载)
                                            factory.passivateObject(underTest);
                                        } catch (final Exception e) {
                                            destroy(underTest);
                                            destroyedByEvictorCount.incrementAndGet();
                                        }
                                    }
                                }
                            }
                            //结束回收测试,更改对象状态或者添加到空闲队列,
                            //如果在此途中被借出,还需重新添加到idleObjects,具体实现请看源码走读(一)
                            if (!underTest.endEvictionTest(idleObjects)) {
                                // TODO - May need to add code here once additional
                                // states are used
                            }
                        }
                    }
                }
            }
            //配置了回收,则进行回收泄漏连接
            final AbandonedConfig ac = this.abandonedConfig;
            if (ac != null && ac.getRemoveAbandonedOnMaintenance()) {
                removeAbandoned(ac);
            }
        }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106

    返回有多少对象需要进行回收测试

        private int getNumTests() {
            final int numTestsPerEvictionRun = getNumTestsPerEvictionRun();
            if (numTestsPerEvictionRun >= 0) {
                return Math.min(numTestsPerEvictionRun, idleObjects.size());
            }
            return (int) (Math.ceil(idleObjects.size() /
                    Math.abs((double) numTestsPerEvictionRun)));
        }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
     
  • 相关阅读:
    简单排序(冒泡、选择、插入)
    配置Tomcat数据源
    使用spring的邮件发送功能
    安装Tomcat
    Spring-MongoDB简单操作
    cisco ASA ios升级或恢复
    ASA 用TFTP 备份配置方法
    DELL MD3200i存储控制器解锁方法
    IBM ServerGuide引导盘全系列下载网址
    ASA5520远程配置 telnet,ssh
  • 原文地址:https://www.cnblogs.com/developer-ios/p/11398599.html
Copyright © 2011-2022 走看看