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,若不是同一個(gè)線程則設(shè)置asyncCloseConnectionEnable為true,若asyncCloseConnectionEnable為true則執(zhí)行syncClose(這里語(yǔ)義貌似相反),否則執(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方法,之后針對(duì)大于等于phyMaxUseCount的場(chǎng)景執(zhí)行discardConnection;針對(duì)testOnReturn為true,則執(zhí)行testConnectionInternal校驗(yàn),校驗(yàn)失敗則關(guān)閉連接;最后加鎖執(zhí)行putLast把連接放回連接池,若歸還失敗則關(guān)閉連接。
小結(jié)
close方法先從holder獲取當(dāng)前的dataSource,然后判斷ownerThread,若不是同一個(gè)線程則設(shè)置asyncCloseConnectionEnable為true,若asyncCloseConnectionEnable為true則執(zhí)行syncClose(這里語(yǔ)義貌似相反),否則執(zhí)行recycle方法。
以上就是druid return行為源碼示例解析的詳細(xì)內(nèi)容,更多關(guān)于druid return行為的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Mybatis generator自動(dòng)生成代碼插件實(shí)例解析
這篇文章主要介紹了Mybatis generator自動(dòng)生成代碼插件實(shí)例解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-09-09java 使用memcached以及spring 配置memcached完整實(shí)例代碼
本篇文章主要介紹了java 使用memcached以及spring 配置memcached完整實(shí)例代碼,具有一定的參考價(jià)值,有興趣的可以了解一下2017-07-07Java獲取時(shí)間差(天數(shù)差,小時(shí)差,分鐘差)代碼示例
這篇文章主要介紹了Java獲取時(shí)間差(天數(shù)差,小時(shí)差,分鐘差)代碼示例,使用SimpleDateFormat來(lái)實(shí)現(xiàn)的相關(guān)代碼,具有一定參考價(jià)值,需要的朋友可以了解下。2017-11-11Java面試之如何實(shí)現(xiàn)10億數(shù)據(jù)判重
當(dāng)數(shù)據(jù)量比較大時(shí),使用常規(guī)的方式來(lái)判重就不行了,所以這篇文章小編主要來(lái)和大家介紹一下Java實(shí)現(xiàn)10億數(shù)據(jù)判重的相關(guān)方法,希望對(duì)大家有所幫助2024-02-02Java 如何通過(guò)Magic 魔數(shù)獲取文件類型
魔數(shù)有很多種定義,這里我們討論的主要是在編程領(lǐng)域的定義,文件的起始幾個(gè)字節(jié)的內(nèi)容是固定的,本文給大家介紹Java Magic 魔數(shù)獲取文件類型的相關(guān)知識(shí),感興趣的朋友一起看看吧2023-11-11minio的下載和springboot整合minio使用方法
本文介紹了如何通過(guò)Docker拉取MinIO鏡像,并創(chuàng)建MinIO容器的過(guò)程,首先,需要在本地創(chuàng)建/data和/conf兩個(gè)目錄用于掛載MinIO的數(shù)據(jù)和配置文件,接下來(lái),通過(guò)docker?run命令啟動(dòng)容器,設(shè)置MinIO的訪問(wèn)端口、用戶名、密碼等信息,感興趣的朋友一起看看吧2024-09-09Java使用easypoi快速導(dǎo)入導(dǎo)出的實(shí)現(xiàn)
這篇文章主要介紹了實(shí)現(xiàn)Java使用easypoi快速導(dǎo)入導(dǎo)出的實(shí)現(xiàn),小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2019-03-03Java中token的存儲(chǔ)和獲取實(shí)例代碼
關(guān)于java獲取微信Token驗(yàn)證的問(wèn)題相信很多人都遇見(jiàn)過(guò),尤其是對(duì)剛接觸微信開(kāi)發(fā)的人來(lái)說(shuō)確實(shí)有點(diǎn)棘手,下面這篇文章主要給大家介紹了關(guān)于Java中token存儲(chǔ)和獲取的相關(guān)資料,需要的朋友可以參考下2022-08-08