入門參考:
官方文檔:
 github.com/alibaba/druid/wiki/DruidDataSource%E9%85%8D%E7%BD%AE
參考其中配置。
                                   ConnectionPool
                              |---------------------------| 
                              |                           |
       getConnection          |                           |    
      (notEmpty.await)        |                           |   
      (lowWater.signal)       |                           |
      (maxActive.await)       |                           |
  <-------------------------- |                           |
  <-------------------------- |                           |
  <-------------------------- |                           |
                              |                           |
                              |                           |
  --------------------------> |                           |
  --------------------------> |                           |    銷毀多余連接的線程
  --------------------------> |                           |    (highWater.awati, idleTimeout.await)
    close                     |                           | --------------------------------------> 
    (highWater.signal)        |                           |
    (maxActive.signal)        |                           |  
                              |                           |
                              |                           |
              產生連接的線程     |                           |
     (lowWater.await)         |                           |
     (notEmpty.signal)        |                           |
  --------------------------> |                           |
                              |                           |
                              |---------------------------|
                              
五個Condition:notEmpty、maxActive、lowWater、hightWater, idleTime
    public Connection createPhysicalConnection(String url, Properties info) throws SQLException {
        Connection conn;
        if (getProxyFilters().size() == 0) {
            conn = getDriver().connect(url, info);
        } else {
            conn = new FilterChainImpl(this).connection_connect(info);
        }
        createCountUpdater.incrementAndGet(this);
        return conn;
    }
對比proxool連接池:
proxool太古老,不方便監控,參數控制等也有些問題:比如
maximumConnectionLifetime 是通過創建時間來控制的:
/**
 * The age in millseconds since this connection was built
 */
long getAge();
以下是過期清理的代碼:
HouseKeeper.sweep()
        // Now to check whether the connection is due for expiry
       if (proxyConnection.getAge() > definition.getMaximumConnectionLifetime()) {
           final String reason = "age is " + proxyConnection.getAge() + "ms";
           // Check whether we can make it offline
           if (proxyConnection.setStatus(ProxyConnectionIF.STATUS_AVAILABLE, ProxyConnectionIF.STATUS_OFFLINE)) {
               if (proxyConnection.setStatus(ProxyConnectionIF.STATUS_OFFLINE, ProxyConnectionIF.STATUS_NULL)) {
                   // It is.  Expire it now .
                   connectionPool.expireProxyConnection(proxyConnection, ConnectionListenerIF.MAXIMUM_CONNECTION_LIFETIME_EXCEEDED, reason, ConnectionPool.REQUEST_EXPIRY);
               }
           } else {
               // Oh no, it's in use.  Never mind, we'll mark it for expiry
               // next time it is available.  This will happen in the
               // putConnection() method.
               proxyConnection.markForExpiry(reason);
               if (log.isDebugEnabled()) {
                   log.debug(connectionPool.displayStatistics() + " - #" + FormatHelper.formatMediumNumber(proxyConnection.getId())
                           + " marked for expiry.");
               }
           } // END if (poolableConnection.setOffline())
       } // END if (poolableConnection.getAge() > maximumConnectionLifetime)   
生產連接池,小于minimumConnectionCount則添加,小于最小空閑數prototypeCount也添加。
Prototyper.sweep()
while (!cancel && connectionPool.isConnectionPoolUp()) {
            String reason = null;
            if (connectionCount >= getDefinition().getMaximumConnectionCount()) {
                // We don't want to make any more that the maximum
                break;
            } else if (connectionCount < getDefinition().getMinimumConnectionCount()) {
                reason = "to achieve minimum of " + getDefinition().getMinimumConnectionCount();
            } else if (connectionPool.getAvailableConnectionCount() < getDefinition().getPrototypeCount()) {
                reason = "to keep " + getDefinition().getPrototypeCount() + " available";
            } else {
                // Nothing to do
                break;
            }
            ProxyConnectionIF freshlyBuiltProxyConnection = null;
            try {
                // If it has been shutdown then we should just stop now.
                if (!connectionPool.isConnectionPoolUp()) {
                    break;
                }
                freshlyBuiltProxyConnection = buildConnection(ConnectionInfoIF.STATUS_AVAILABLE, reason);
                somethingDone = true;
            } catch (Throwable e) {
                log.error("Prototype", e);
            }
}以上就會造成非高峰期時間段內,如果最小值配的比較大,會固定回收時間重新創建一次連接池的最小個數。
而druid沒有這(zhe)個問題:
DruidDataSource.shrink()
for (int i = 0; i < poolingCount; ++i) {
            DruidConnectionHolder connection = connections[i];
            if (checkTime) {
                if (phyTimeoutMillis > 0) {
                    long phyConnectTimeMillis = currentTimeMillis - connection.connectTimeMillis;
                    if (phyConnectTimeMillis > phyTimeoutMillis) {
                        evictConnections[evictCount++] = connection;
                        continue;
                    }
                }
                long idleMillis = currentTimeMillis - connection.lastActiveTimeMillis;
                if (idleMillis < minEvictableIdleTimeMillis) {
                    break;
                }
                if (checkTime && i < checkCount) {
                    evictConnections[evictCount++] = connection;
                } else if (idleMillis > maxEvictableIdleTimeMillis) {
                    evictConnections[evictCount++] = connection;
                } else if (keepAlive) {
                    keepAliveConnections[keepAliveCount++] = connection;
                }
            } else {
                if (i < checkCount) {
                    evictConnections[evictCount++] = connection;
                } else {
                    break;
                }
            }
        }