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爲任意對象提供健壯的池功能。java

您能夠選擇性的配置池來檢查和可能回收池中的空閒對象,並確保有最少數量的空閒對象可用。這是由一個「空閒對象回收」線程(即BaseGenericObjectPool <T> 的Evictor)執行的,線程是異步運行的。在配置這個可選特性時,應該謹慎使用。驅逐運行與客戶端線程爭用池中的對象,所以若是它們運行得太頻繁,可能會致使性能問題。apache

還能夠配置池來檢測和刪除被泄漏的對象,好比一個從池中借出的對象,在超過removeAbandonedTimeout超時以前既不使用也不返回。移除泄漏的鏈接,可能發生在對象被借用時對象池已接近飽和,也多是被回收線程檢查出,或者二者都執行時。若是池對象實現了TrackedUse接口,那麼其最後一次使用時間使取決於getLastUsed方法;不然,是由對象從池中借出的時間決定。安全

實現注意:爲了防止可能的死鎖,已經採起了謹慎措施,以確保在同步塊中不會發生對工廠方法的調用。這個類線程安全。markdown

一、接口繼承、實現關係

GenericObjectPool <T> 實現了ObjectPool<T> 具有對象池的功能,同時 繼承了BaseGenericObjectPool<T> 的對於對象狀態管理和回收等功能。 
這裏寫圖片描述多線程

二、構造函數

構造函數經過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

三、相關屬性

// --- 可配置的屬性 ------------------------------------------------- //最大空閒數量 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

四、 對象池方法實現

  • 借用對象 
    整個流程爲,檢查池是否關閉 –> 是否回收泄漏對象 –> 是否阻塞建立對象 –> 建立對象 –> 分配對象 –> 激活對象 –> 校驗對象 –> 更改借用信息 –> 返回對象
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

建立對象 
當借用時,空閒對象爲空,而且未達到池最大數量,則會調用該方法從新建立一個空閒對象app

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
相關文章
相關標籤/搜索