// 连接池瘦身
public void shrink(boolean checkTime, boolean keepAlive) {
    try {
        lock.lockInterruptibly();
    } catch (InterruptedException e) {
        return;
    }

    boolean needFill = false;
    int evictCount = 0;
    int keepAliveCount = 0;
    int fatalErrorIncrement = fatalErrorCount - fatalErrorCountLastShrink;
    fatalErrorCountLastShrink = fatalErrorCount;
    
    try {
        if (!inited) {
            return;
        }

        // 根据 poolingCount 和 minIdle 计算出 evictCheck(丢弃检查) 的范围
        final int checkCount = poolingCount - minIdle;
        final long currentTimeMillis = System.currentTimeMillis();
        // 开始遍历连接池里闲置的连接
        for (int i = 0; i < poolingCount; ++i) {
            DruidConnectionHolder connection = connections[i];

            if ((onFatalError || fatalErrorIncrement > 0) && (lastFatalErrorTimeMillis > connection.connectTimeMillis))  {
                keepAliveConnections[keepAliveCount++] = connection;
                continue;
            }

            // 除非手动调用,不然经过主流程4触发,一般为 true
            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
                        && idleMillis < keepAliveBetweenTimeMillis
                ) {
                    break;
                }

                // 达到需要丢弃的阈值时,则判断连接下标是否在 evictCheck 范围,若在,则视为“可以丢弃的对象”放入e victConnections 数组
                if (idleMillis >= minEvictableIdleTimeMillis) {
                    if (checkTime && i < checkCount) {
                        evictConnections[evictCount++] = connection;
                        continue;
                    } else if (idleMillis > maxEvictableIdleTimeMillis) {
                        evictConnections[evictCount++] = connection;
                        continue;
                    }
                }

                // 如果上面的条件均没有命中,如果 keepAlive 为 true,则判断是不是超过了闲置连接检查其活性的频次阈值(即由 keepAliveBetweenTimeMillis 控制)
                if (keepAlive && idleMillis >= keepAliveBetweenTimeMillis) {
                    // 满足条件则视为“需要检测活性的对象”,放入 keepAliveConnections 数组
                    keepAliveConnections[keepAliveCount++] = connection;
                }
            } else {
                if (i < checkCount) {
                    evictConnections[evictCount++] = connection;
                } else {
                    break;
                }
            }
        }

        // 这一批需要移除特殊处理的连接总数
        int removeCount = evictCount + keepAliveCount;
        if (removeCount > 0) {
            // 根据当前移除的元素,把剩余的元素移动至数组首部(参考流程4.1)
            System.arraycopy(connections, removeCount, connections, 0, poolingCount - removeCount);
            // 剩余位置清空
            Arrays.fill(connections, poolingCount - removeCount, poolingCount, null);
            poolingCount -= removeCount;
        }
        keepAliveCheckCount += keepAliveCount;

        if (keepAlive && poolingCount + activeCount < minIdle) {
            needFill = true;
        }
    } finally {
        lock.unlock();
    }

    // 如果需要丢弃的连接数量大于 0
    if (evictCount > 0) {
        for (int i = 0; i < evictCount; ++i) {
            DruidConnectionHolder item = evictConnections[i];
            Connection connection = item.getConnection();
            // 直接关闭连接(这里是直接关闭驱动连接,不再放回池子)
            JdbcUtils.close(connection);
            destroyCountUpdater.incrementAndGet(this);
        }
        // 将 evictConnections 数组重新置空(方便下次使用)
        Arrays.fill(evictConnections, null);
    }

    // 检测那些需要判活的连接数
    if (keepAliveCount > 0) {
        // keep order
        for (int i = keepAliveCount - 1; i >= 0; --i) {
            DruidConnectionHolder holer = keepAliveConnections[i];
            Connection connection = holer.getConnection();
            holer.incrementKeepAliveCheckCount();

            boolean validate = false;
            try {
                // 检测其活性
                this.validateConnection(connection);
                validate = true;
            } catch (Throwable error) {
                if (LOG.isDebugEnabled()) {
                    LOG.debug("keepAliveErr", error);
                }
                // skip
            }

            boolean discard = !validate;
            // 检测通过
            if (validate) {
                holer.lastKeepTimeMillis = System.currentTimeMillis();
                // 检测通过后,再次放入池子
                boolean putOk = put(holer, 0L, true);
                if (!putOk) {
                    // 放不进去池子(说明已经达到连接池最大连接数阈值 maxActive),则视为可以“直接抛弃”的连接
                    discard = true;
                }
            }

            if (discard) {
                try {
                    // 如果可以抛弃,则直接关闭连接(直接调用驱动的 close)
                    connection.close();
                } catch (Exception e) {
                    // skip
                }

                lock.lock();
                try {
                    // 抛弃连接数累加
                    discardCount++;

                    if (activeCount + poolingCount <= minIdle) {
                        // 唤起主流程3追加连接对象
                        emptySignal();
                    }
                } finally {
                    lock.unlock();
                }
            }
        }
        this.getDataSourceStat().addKeepAliveCheckCount(keepAliveCount);
        // 将 keepAliveConnections 数组重新置空(方便下次使用)
        Arrays.fill(keepAliveConnections, null);
    }

    if (needFill) {
        lock.lock();
        try {
            int fillCount = minIdle - (activeCount + poolingCount + createTaskCount);
            for (int i = 0; i < fillCount; ++i) {
                emptySignal();
            }
        } finally {
            lock.unlock();
        }
    } else if (onFatalError || fatalErrorIncrement > 0) {
        lock.lock();
        try {
            emptySignal();
        } finally {
            lock.unlock();
        }
    }
}

// 上面检测通过,再次通过该方法重新把连接放入池子
private boolean put(DruidConnectionHolder holder, long createTaskId, boolean checkExists) {
    lock.lock();
    try {
        if (this.closing || this.closed) {
            return false;
        }

        // 若池子内闲置连接数超过 maxActive,则无法继续添加新的连接进来,返回 false
        if (poolingCount >= maxActive) {
            if (createScheduler != null) {
                clearCreateTask(createTaskId);
            }
            return false;
        }

        if (checkExists) {
            for (int i = 0; i < poolingCount; i++) {
                if (connections[i] == holder) {
                    return false;
                }
            }
        }

        // 否则直接把此连接对象放入连接池队尾
        connections[poolingCount] = holder;
        incrementPoolingCount();

        if (poolingCount > poolingPeak) {
            poolingPeak = poolingCount;
            poolingPeakTime = System.currentTimeMillis();
        }

        // 唤起那些因获取不到可用连接而陷入阻塞状态的业务线程一次
        notEmpty.signal();
        notEmptySignalCount++;

        // 不启用该模式,忽略
        if (createScheduler != null) {
            clearCreateTask(createTaskId);

            if (poolingCount + createTaskCount < notEmptyWaitThreadCount //
                && activeCount + poolingCount + createTaskCount < maxActive) {
                emptySignal();
            }
        }
    } finally {
        lock.unlock();
    }
    return true;
}