对象池common-pool源码分析

前几天在看一个应用的日志时,发现与MySQL连接时发生如下错误:

The last packet successfully received from the server was XXXXXX seconds ago.
The last packet sent successfully to the server was XXXXXX seconds ago,

大概意思是距离上一次连接MySQL的间隔时间,已经超出了MySQL设置的'wait_timeout'时长啦。


查看dbcp的源码



public class GenericObjectPool extends BaseObjectPool implements ObjectPool {


    public GenericObjectPool(){
     
     //从ObjectPool创建开始启动回收定时任务,timeBetweenEvictionRunsMillis为回收时间间隔
     startEvictor(_timeBetweenEvictionRunsMillis);
   }


     protected synchronized void startEvictor(long delay) {
        if(null != _evictor) {
            EvictionTimer.cancel(_evictor);
            _evictor = null;
        }
        if(delay > 0) {
            _evictor = new Evictor();
            EvictionTimer.schedule(_evictor, delay, delay);
        }
    }


     
     private class Evictor extends TimerTask {
        /**
         * Run pool maintenance.  Evict objects qualifying for eviction and then
         * invoke {@link GenericObjectPool#ensureMinIdle()}.
         */
        public void run() {
            try {
               //1.回收池对象
                evict();
            } catch(Exception e) {
                // ignored
            } 
            try {
               //2.确保最小的空闲数
                ensureMinIdle();
            } catch(Exception e) {
                // ignored
            }
        }
    }

   
    public void evict() throws Exception {
        assertOpen();
        synchronized (this) {
            if(_pool.isEmpty()) {
                return;
            }
            if (null == _evictionCursor) {
                _evictionCursor = (_pool.cursor(_lifo ? _pool.size() : 0));
            }
        }

       //numTestsPerEvictionRun可以设置
        for (int i=0,m=getNumTests();i 0) &&
                    (idleTimeMilis > getMinEvictableIdleTimeMillis())) {
                removeObject = true;
            } else if ((getSoftMinEvictableIdleTimeMillis() > 0) &&
                    (idleTimeMilis > getSoftMinEvictableIdleTimeMillis()) &&
                    ((getNumIdle() + 1)> getMinIdle())) { // +1 accounts for object we are processing
                removeObject = true;
            }
            if(getTestWhileIdle() && !removeObject) {
                boolean active = false;
                try {
                    _factory.activateObject(pair.value);
                    active = true;
                } catch(Exception e) {
                    removeObject=true;
                }
                if(active) {
                    //验证失败,需要回收对象
                    if(!_factory.validateObject(pair.value)) {
                        removeObject=true;
                    } else {
                        try {
                            _factory.passivateObject(pair.value);
                        } catch(Exception e) {
                            removeObject=true;
                        }
                    }
                }
            }


            if (removeObject) {
                try {
                    //工厂销毁对象
                    _factory.destroyObject(pair.value);
                } catch(Exception e) {
                    // ignored
                }
            }
            synchronized (this) {
                if(!removeObject) {
                    _evictionCursor.add(pair);
                    if (_lifo) {
                        // Skip over the element we just added back
                        _evictionCursor.previous();
                    }
                }
                _numInternalProcessing--;
            }
        }
    }



   public Object borrowObject() throws Exception {
      //pool会一直borrow直到创建成功
       for(;;) {

        if(latch.getPair() == null) {
  
            try {
                synchronized (latch) {
                // Before we wait, make sure another thread didn't allocate us an object
                // or permit a new object to be created
                if (latch.getPair() == null && !latch.mayCreate()) {
                  if(maxWait <= 0) {
                        latch.wait();
                   } else {
                      // this code may be executed again after a notify then continue cycle
                     // so, need to calculate the amount of time to wait
                     final long elapsed = (System.currentTimeMillis() - starttime);
                     final long waitTime = maxWait - elapsed;
                     if (waitTime > 0)
                      {
                          latch.wait(waitTime);
                       }
                    }
                  } else {
                     break;
                  }
                 }
               } catch(InterruptedException e) {
                      Thread.currentThread().interrupt();
                      throw e;
               }
              if(maxWait > 0 && ((System.currentTimeMillis() - starttime) >= maxWait)) {
                  synchronized(this) {
                 // Make sure allocate hasn't already assigned an object
                // in a different thread or permitted a new object to be created
               if (latch.getPair() == null && !latch.mayCreate()) {
                // Remove latch from the allocation queue
               _allocationQueue.remove(latch);
                } else {
                    break;
                }
             }
                throw new NoSuchElementException("Timeout waiting for idle object");
              } else {
                continue; // keep looping
            }

         }


           //factory makeObject
            boolean newlyCreated = false;
            if(null == latch.getPair()) {
                try {
                    Object obj = _factory.makeObject();
                    latch.setPair(new ObjectTimestampPair(obj));
                    newlyCreated = true;
                } finally {
                    if (!newlyCreated) {
                        // object cannot be created
                        synchronized (this) {
                            _numInternalProcessing--;
                            // No need to reset latch - about to throw exception
                            allocate();
                        }
                    }
                }
            }



       
         try {
               //factory activateObject
               _factory.activateObject(latch.getPair().value);
               //testOnBorrow可以自己设置
                if(_testOnBorrow &&
                        !_factory.validateObject(latch.getPair().value)) {
                    throw new Exception("ValidateObject failed");
                }
                synchronized(this) {
                    _numInternalProcessing--;
                    _numActive++;
                }
                return latch.getPair().value;
            }
            catch (Throwable e) {
                // object cannot be activated or is invalid
                try {
                    _factory.destroyObject(latch.getPair().value);
                } catch (Throwable e2) {
                    // cannot destroy broken object
                }
                synchronized (this) {
                    _numInternalProcessing--;
                    if (!newlyCreated) {
                        latch.reset();
                        _allocationQueue.add(0, latch);
                    }
                    allocate();
                }
                //创建后的对象,验证失败后会抛异常
                if(newlyCreated) {
                    throw new NoSuchElementException("Could not create a validated object, cause: " + e.getMessage());
                }
                else {
                    continue; // keep looping
                }
            }
        }

     }


  }



    /**
     * 归还对象
    **/
   public void returnObject(Object obj) throws Exception {
            try {
                addObjectToPool(obj, true);
            } catch (Exception e) {
               ....
            }
        }

   private void addObjectToPool(Object obj, boolean decrementNumActive) throws Exception {
        boolean success = true; 
        //testOnBorrow参数可配置,testOnBorrow为true时,归回后验证失败会将对象销毁
        if (_testOnReturn && !(_factory.validateObject(obj))) {
            success = false;
        } else {
            _factory.passivateObject(obj);
        }
        boolean shouldDestroy = !success; 
      // Add instance to pool if there is room and it has passed validation 
      // (if testOnreturn is set) 
        synchronized (this) {
            if (isClosed()) {
                shouldDestroy = true;
            } else {
                if((_maxIdle >= 0) && (_pool.size() >= _maxIdle)) {
                    shouldDestroy = true;
                } else if(success) {
                    // borrowObject always takes the first element from the queue,
                    // so for LIFO, push on top, FIFO add to end
                    if (_lifo) {
                        _pool.addFirst(new ObjectTimestampPair(obj));
                    } else {
                        _pool.addLast(new ObjectTimestampPair(obj));
                    }
                    if (decrementNumActive) {
                        _numActive--;
                    }
                    allocate();
                }
            }
        }
  }


  
 
  

总结

1.超过minEvictableIdleTimeMillis对象会被destroy

2.testWhileIdle为true时,对象的minEvictableIdleTimeMillis内也会validateObject对象是否有效,无效对象将被destroy

下面看看PoolableConnectionFactory


public class PoolableConnectionFactory implements PoolableObjectFactory {


      public void activateObject(Object obj) throws Exception {
        if (conn.getAutoCommit() != _defaultAutoCommit) {
                conn.setAutoCommit(_defaultAutoCommit);
            }
        

     }




     public void destroyObject(Object obj) throws Exception {
        if(obj instanceof PoolableConnection) {
            ((PoolableConnection)obj).reallyClose();
        }
    }

     public boolean validateObject(Object obj) {
         String query = _validationQuery;
        if(conn.isClosed()) {
            throw new SQLException("validateConnection: connection closed");
        }

         rset = stmt.executeQuery(query);



    } 


}












你可能感兴趣的:(Java)