上一篇主要分析了獲取連接,本篇分析歸還連接與連接清理。歸還連接基本上就一個入口:
- protected void returnConnection(PooledConnection con) {
- if (isClosed()) {
- //if the connection pool is closed
- //close the connection instead of returning it
- release(con);
- return;
- } //end if
- if (con != null) {
- try {
- con.lock();
- if (busy.remove(con)) {
- if (!shouldClose(con,PooledConnection.VALIDATE_RETURN)) {
- con.setStackTrace(null);
- con.setTimestamp(System.currentTimeMillis());
- if (((idle.size()>=poolProperties.getMaxIdle()) && !poolProperties.isPoolSweeperEnabled()) || (!idle.offer(con))) {
- if (log.isDebugEnabled()) {
- log.debug("Connection ["+con+"] will be closed and not returned to the pool, idle["+idle.size()+"]>=maxIdle["+poolProperties.getMaxIdle()+"] idle.offer failed.");
- }
- release(con);
- }
- } else {
- if (log.isDebugEnabled()) {
- log.debug("Connection ["+con+"] will be closed and not returned to the pool.");
- }
- release(con);
- } //end if
- } else {
- if (log.isDebugEnabled()) {
- log.debug("Connection ["+con+"] will be closed and not returned to the pool, busy.remove failed.");
- }
- release(con);
- }
- } finally {
- con.unlock();
- }
- } //end if
- } //
先看連接池有沒有關閉,如果在關閉狀態,則調用release(con)關閉該連接。
獲取當前連接的鎖,從繁忙隊列中移除該連接。放入空閒隊列中以備其他請求使用。有以下幾種情況,該連接會直接關閉,而非放入空閒隊列。
1. 從繁忙隊列中移除該連接時失敗。(此現象很少見)
2. 空閒連接數大小允許的最大空閒連接數,且沒有啓用空閒連接清理器。
3. 放入空閒隊列失敗。(與1比較類似,比較少見)
可以看出歸還連接比較簡單。
對於連接清理,連接池提供了一個Timer來完成:
class PoolCleaner extends TimerTask
該Timer主要清理三個方面的連接。
1. 需要丟棄的連接,從繁忙隊列清除。
這類連接主要是長期沒有歸還的連接。連接池提供了兩個時間值:AbandonTimeout和SuspectTimeout。對於超過AbandonTimeout連接,如果Pool當前符合清理Abandon連接的條件,則執行關閉。
對於大於的SuspectTimeout的連接,輸出日誌提醒。
2. 空閒的連接,從空閒隊列中清除。
關閉空閒時間過長的連接,沒什麼好說的。
3. 對空閒連接進行驗證(如果),驗證失敗的連接。
VALIDATE_IDLE驗證方式是用戶指定的用於以空閒連接進行驗證策略,意議不大。