druid?return行為方法源碼示例解析
序
本文主要研究一下druid的return行為
close
com/alibaba/druid/pool/DruidPooledConnection.java
@Override public void close() throws SQLException { if (this.disable) { return; } DruidConnectionHolder holder = this.holder; if (holder == null) { if (dupCloseLogEnable) { LOG.error("dup close"); } return; } DruidAbstractDataSource dataSource = holder.getDataSource(); boolean isSameThread = this.getOwnerThread() == Thread.currentThread(); if (!isSameThread) { dataSource.setAsyncCloseConnectionEnable(true); } if (dataSource.isAsyncCloseConnectionEnable()) { syncClose(); return; } if (!CLOSING_UPDATER.compareAndSet(this, 0, 1)) { return; } try { for (ConnectionEventListener listener : holder.getConnectionEventListeners()) { listener.connectionClosed(new ConnectionEvent(this)); } List<Filter> filters = dataSource.getProxyFilters(); if (filters.size() > 0) { FilterChainImpl filterChain = new FilterChainImpl(dataSource); filterChain.dataSource_recycle(this); } else { recycle(); } } finally { CLOSING_UPDATER.set(this, 0); } this.disable = true; }
close方法先從holder獲取當(dāng)前的dataSource,然后判斷ownerThread,若不是同一個線程則設(shè)置asyncCloseConnectionEnable為true,若asyncCloseConnectionEnable為true則執(zhí)行syncClose(這里語義貌似相反),否則執(zhí)行recycle方法
syncClose
com/alibaba/druid/pool/DruidPooledConnection.java
public void syncClose() throws SQLException { lock.lock(); try { if (this.disable || CLOSING_UPDATER.get(this) != 0) { return; } DruidConnectionHolder holder = this.holder; if (holder == null) { if (dupCloseLogEnable) { LOG.error("dup close"); } return; } if (!CLOSING_UPDATER.compareAndSet(this, 0, 1)) { return; } for (ConnectionEventListener listener : holder.getConnectionEventListeners()) { listener.connectionClosed(new ConnectionEvent(this)); } DruidAbstractDataSource dataSource = holder.getDataSource(); List<Filter> filters = dataSource.getProxyFilters(); if (filters.size() > 0) { FilterChainImpl filterChain = new FilterChainImpl(dataSource); filterChain.dataSource_recycle(this); } else { recycle(); } this.disable = true; } finally { CLOSING_UPDATER.set(this, 0); lock.unlock(); } }
syncClose方法主要是加鎖執(zhí)行recycle
recycle
public void recycle() throws SQLException { if (this.disable) { return; } DruidConnectionHolder holder = this.holder; if (holder == null) { if (dupCloseLogEnable) { LOG.error("dup close"); } return; } if (!this.abandoned) { DruidAbstractDataSource dataSource = holder.getDataSource(); dataSource.recycle(this); } this.holder = null; conn = null; transactionInfo = null; closed = true; }
recycle方法主要是執(zhí)行dataSource.recycle(this)
DruidDataSource.recycle
com/alibaba/druid/pool/DruidDataSource.java
protected void recycle(DruidPooledConnection pooledConnection) throws SQLException { final DruidConnectionHolder holder = pooledConnection.holder; if (holder == null) { LOG.warn("connectionHolder is null"); return; } if (logDifferentThread // && (!isAsyncCloseConnectionEnable()) // && pooledConnection.ownerThread != Thread.currentThread()// ) { LOG.warn("get/close not same thread"); } final Connection physicalConnection = holder.conn; if (pooledConnection.traceEnable) { Object oldInfo = null; activeConnectionLock.lock(); try { if (pooledConnection.traceEnable) { oldInfo = activeConnections.remove(pooledConnection); pooledConnection.traceEnable = false; } } finally { activeConnectionLock.unlock(); } if (oldInfo == null) { if (LOG.isWarnEnabled()) { LOG.warn("remove abandonded failed. activeConnections.size " + activeConnections.size()); } } } final boolean isAutoCommit = holder.underlyingAutoCommit; final boolean isReadOnly = holder.underlyingReadOnly; final boolean testOnReturn = this.testOnReturn; try { // check need to rollback? if ((!isAutoCommit) && (!isReadOnly)) { pooledConnection.rollback(); } // reset holder, restore default settings, clear warnings boolean isSameThread = pooledConnection.ownerThread == Thread.currentThread(); if (!isSameThread) { final ReentrantLock lock = pooledConnection.lock; lock.lock(); try { holder.reset(); } finally { lock.unlock(); } } else { holder.reset(); } if (holder.discard) { return; } if (phyMaxUseCount > 0 && holder.useCount >= phyMaxUseCount) { discardConnection(holder); return; } if (physicalConnection.isClosed()) { lock.lock(); try { if (holder.active) { activeCount--; holder.active = false; } closeCount++; } finally { lock.unlock(); } return; } if (testOnReturn) { boolean validate = testConnectionInternal(holder, physicalConnection); if (!validate) { JdbcUtils.close(physicalConnection); destroyCountUpdater.incrementAndGet(this); lock.lock(); try { if (holder.active) { activeCount--; holder.active = false; } closeCount++; } finally { lock.unlock(); } return; } } if (holder.initSchema != null) { holder.conn.setSchema(holder.initSchema); holder.initSchema = null; } if (!enable) { discardConnection(holder); return; } boolean result; final long currentTimeMillis = System.currentTimeMillis(); if (phyTimeoutMillis > 0) { long phyConnectTimeMillis = currentTimeMillis - holder.connectTimeMillis; if (phyConnectTimeMillis > phyTimeoutMillis) { discardConnection(holder); return; } } lock.lock(); try { if (holder.active) { activeCount--; holder.active = false; } closeCount++; result = putLast(holder, currentTimeMillis); recycleCount++; } finally { lock.unlock(); } if (!result) { JdbcUtils.close(holder.conn); LOG.info("connection recyle failed."); } } catch (Throwable e) { holder.clearStatementCache(); if (!holder.discard) { discardConnection(holder); holder.discard = true; } LOG.error("recyle error", e); recycleErrorCountUpdater.incrementAndGet(this); } } boolean putLast(DruidConnectionHolder e, long lastActiveTimeMillis) { if (poolingCount >= maxActive || e.discard || this.closed) { return false; } e.lastActiveTimeMillis = lastActiveTimeMillis; connections[poolingCount] = e; incrementPoolingCount(); if (poolingCount > poolingPeak) { poolingPeak = poolingCount; poolingPeakTime = lastActiveTimeMillis; } notEmpty.signal(); notEmptySignalCount++; return true; }
recycle方法先執(zhí)行DruidConnectionHolder的reset方法,之后針對大于等于phyMaxUseCount的場景執(zhí)行discardConnection;針對testOnReturn為true,則執(zhí)行testConnectionInternal校驗,校驗失敗則關(guān)閉連接;最后加鎖執(zhí)行putLast把連接放回連接池,若歸還失敗則關(guān)閉連接。
小結(jié)
close方法先從holder獲取當(dāng)前的dataSource,然后判斷ownerThread,若不是同一個線程則設(shè)置asyncCloseConnectionEnable為true,若asyncCloseConnectionEnable為true則執(zhí)行syncClose(這里語義貌似相反),否則執(zhí)行recycle方法。
以上就是druid return行為源碼示例解析的詳細(xì)內(nèi)容,更多關(guān)于druid return行為的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
java 使用memcached以及spring 配置memcached完整實例代碼
本篇文章主要介紹了java 使用memcached以及spring 配置memcached完整實例代碼,具有一定的參考價值,有興趣的可以了解一下2017-07-07Java獲取時間差(天數(shù)差,小時差,分鐘差)代碼示例
這篇文章主要介紹了Java獲取時間差(天數(shù)差,小時差,分鐘差)代碼示例,使用SimpleDateFormat來實現(xiàn)的相關(guān)代碼,具有一定參考價值,需要的朋友可以了解下。2017-11-11Java面試之如何實現(xiàn)10億數(shù)據(jù)判重
當(dāng)數(shù)據(jù)量比較大時,使用常規(guī)的方式來判重就不行了,所以這篇文章小編主要來和大家介紹一下Java實現(xiàn)10億數(shù)據(jù)判重的相關(guān)方法,希望對大家有所幫助2024-02-02minio的下載和springboot整合minio使用方法
本文介紹了如何通過Docker拉取MinIO鏡像,并創(chuàng)建MinIO容器的過程,首先,需要在本地創(chuàng)建/data和/conf兩個目錄用于掛載MinIO的數(shù)據(jù)和配置文件,接下來,通過docker?run命令啟動容器,設(shè)置MinIO的訪問端口、用戶名、密碼等信息,感興趣的朋友一起看看吧2024-09-09Java使用easypoi快速導(dǎo)入導(dǎo)出的實現(xiàn)
這篇文章主要介紹了實現(xiàn)Java使用easypoi快速導(dǎo)入導(dǎo)出的實現(xiàn),小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2019-03-03