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
 

转载于:https://www.cnblogs.com/developer-ios/p/11398599.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值