java was datasource_mybatis默认的数据源连接池(PooledDataSource和UnPooledDataSource)

本文深入解析PooledDataSource类的实现细节,包括其如何管理和维护数据库连接池中的活动连接和空闲连接,以及如何通过配置参数调整连接池的行为。此外,还介绍了如何安全地获取和返回数据库连接。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

public classPooledDataSource implements DataSource {private static final Log log = LogFactory.getLog(PooledDataSource.class);

//PollState 充当锁对象,这个对象中也有例如 空闲连接集合,活跃链接集合,请求的数量,等一些变量private final PoolState state = new PoolState(this);

//PolledDataSource中的数据源也是使用的UnpolledDataSource对象来实现的privatefinal UnpooledDataSource dataSource;//OPTIONAL CONFIGURATION FIELDS 线程池的最大活跃数量,最大空闲数量,等待时间等等。。。

protected int poolMaximumActiveConnections = 10;protected int poolMaximumIdleConnections = 5;protected int poolMaximumCheckoutTime = 20000;protected int poolTimeToWait = 20000;protected int poolMaximumLocalBadConnectionTolerance = 3;protected String poolPingQuery = "NO PING QUERY SET";protectedboolean poolPingEnabled;protected intpoolPingConnectionsNotUsedFor;

//url+username+password连接起来的字符串的hashcode值private intexpectedConnectionTypeCode;publicPooledDataSource() {

dataSource= newUnpooledDataSource();

}publicPooledDataSource(UnpooledDataSource dataSource) {this.dataSource =dataSource;

}publicPooledDataSource(String driver, String url, String username, String password) {

dataSource= newUnpooledDataSource(driver, url, username, password); expectedConnectionTypeCode=assembleConnectionTypeCode(dataSource.getUrl(), dataSource.getUsername(), dataSource.getPassword());

}

//获取连接connection

@OverridepublicConnection getConnection() throws SQLException {returnpopConnection(dataSource.getUsername(), dataSource.getPassword()).getProxyConnection();

}

@OverridepublicConnection getConnection(String username, String password) throws SQLException {returnpopConnection(username, password).getProxyConnection();

}

//线程安全的获取连接的方法(供PooledConnection中调用) synchronizedprotected voidpushConnection(PooledConnection conn) throws SQLException {

//所对象为PoolState

synchronized (state) {

state.activeConnections.remove(conn);if(conn.isValid()) {if (state.idleConnections.size() < poolMaximumIdleConnections && conn.getConnectionTypeCode() ==expectedConnectionTypeCode) {

state.accumulatedCheckoutTime+=conn.getCheckoutTime();if (!conn.getRealConnection().getAutoCommit()) {

conn.getRealConnection().rollback();

}

PooledConnection newConn= new PooledConnection(conn.getRealConnection(), this);

state.idleConnections.add(newConn);

newConn.setCreatedTimestamp(conn.getCreatedTimestamp());

newConn.setLastUsedTimestamp(conn.getLastUsedTimestamp());

conn.invalidate();if(log.isDebugEnabled()) {

log.debug("Returned connection" + newConn.getRealHashCode() + "to pool.");

}

state.notifyAll();

}else{

state.accumulatedCheckoutTime+=conn.getCheckoutTime();if (!conn.getRealConnection().getAutoCommit()) {

conn.getRealConnection().rollback();

}

conn.getRealConnection().close();if(log.isDebugEnabled()) {

log.debug("Closed connection" + conn.getRealHashCode() + ".");

}

conn.invalidate();

}

}else{if(log.isDebugEnabled()) {

log.debug("A bad connection (" + conn.getRealHashCode() + ") attempted to return to the pool, discarding connection.");

}

state.badConnectionCount++;

}

}

}privatePooledConnection popConnection(String username, String password) throws SQLException {

boolean countedWait= false;

PooledConnection conn= null;long t =System.currentTimeMillis();int localBadConnectionCount = 0;while (conn == null) {

synchronized (state) {

//如果state中空闲的连接不为空时,直接从state中的idelConnections集合中获取if (!state.idleConnections.isEmpty()) {//Pool has available connection

conn = state.idleConnections.remove(0);if(log.isDebugEnabled()) {

log.debug("Checked out connection" + conn.getRealHashCode() + "from pool.");

}

}else{

//state中的idelConnections集合中没有连接connection了,判断活跃的connection是否小于最大活跃线程数,小于的话就新建一个connection//Pool does not have available connection

if (state.activeConnections.size()

conn = new PooledConnection(dataSource.getConnection(), this);if(log.isDebugEnabled()) {

log.debug("Created connection" + conn.getRealHashCode() + ".");

}

}else{

//当前活跃的connection数大于最大活跃connection数是,表明不能新建connection,这种情况下,会判断是否已经超过设定的时间20s,如果超过,会根据是否自动commit,

/不是自动提交,会进行rollback操作//Cannot create new connection

PooledConnection oldestActiveConnection = state.activeConnections.get(0);long longestCheckoutTime =oldestActiveConnection.getCheckoutTime();if (longestCheckoutTime >poolMaximumCheckoutTime) {//判断是否超时//Can claim overdue connection

state.claimedOverdueConnectionCount++;

state.accumulatedCheckoutTimeOfOverdueConnections+=longestCheckoutTime;

state.accumulatedCheckoutTime+=longestCheckoutTime;

state.activeConnections.remove(oldestActiveConnection);if (!oldestActiveConnection.getRealConnection().getAutoCommit()) {//判断是否设置了自动提交,不是自动提交的话,会进行rollbacktry{

oldestActiveConnection.getRealConnection().rollback();

}catch(SQLException e) {/*Just log a message for debug and continue to execute the following

statement like nothing happend.

Wrap the bad connection with a new PooledConnection, this will help

to not intterupt current executing thread and give current thread a

chance to join the next competion for another valid/good database

connection. At the end of this loop, bad {@link @conn} will be set as null.*/log.debug("Bad connection. Could not roll back");

}

}

//将之前rollback的connection进行处理,重新生成一个connection,并设置创建时间和最后使用时间

conn= new PooledConnection(oldestActiveConnection.getRealConnection(), this);

conn.setCreatedTimestamp(oldestActiveConnection.getCreatedTimestamp());

conn.setLastUsedTimestamp(oldestActiveConnection.getLastUsedTimestamp());

oldestActiveConnection.invalidate();if(log.isDebugEnabled()) {

log.debug("Claimed overdue connection" + conn.getRealHashCode() + ".");

}

}else{

//当活跃connection的集合中第一个connection不符合超时,则进行等待wait//Must wait

try{if (!countedWait) {

state.hadToWaitCount++;

countedWait= true;

}

//pooltimeTowait默认也是20秒if(log.isDebugEnabled()) {

log.debug("Waiting as long as" + poolTimeToWait + "milliseconds for connection.");

}long wt =System.currentTimeMillis();

state.wait(poolTimeToWait);

state.accumulatedWaitTime+= System.currentTimeMillis() -wt;

}catch(InterruptedException e) {break;

}

}

}

}

//经过以上处理,如果conn仍然没有值,则会循环走一行流程,第二次一定会获取到conn对象(默认的超时时间是20秒,第一次已经等待过20s了)if (conn != null) {

//判断conn是否能用 通过ping能否ping通//ping to server and check the connection is valid or not

if(conn.isValid()) {if (!conn.getRealConnection().getAutoCommit()) {

conn.getRealConnection().rollback();

}

conn.setConnectionTypeCode(assembleConnectionTypeCode(dataSource.getUrl(), username, password));

conn.setCheckoutTimestamp(System.currentTimeMillis());

conn.setLastUsedTimestamp(System.currentTimeMillis());

state.activeConnections.add(conn);

state.requestCount++;

state.accumulatedRequestTime+= System.currentTimeMillis() -t;

}else{if(log.isDebugEnabled()) {

log.debug("A bad connection (" + conn.getRealHashCode() + ") was returned from the pool, getting another connection.");

}

state.badConnectionCount++;

localBadConnectionCount++;

conn= null;if (localBadConnectionCount > (poolMaximumIdleConnections +poolMaximumLocalBadConnectionTolerance)) {if(log.isDebugEnabled()) {

log.debug("PooledDataSource: Could not get a good connection to the database.");

}throw new SQLException("PooledDataSource: Could not get a good connection to the database.");

}

}

}

}

}if (conn == null) {if(log.isDebugEnabled()) {

log.debug("PooledDataSource: Unknown severe error condition. The connection pool returned a null connection.");

}throw new SQLException("PooledDataSource: Unknown severe error condition. The connection pool returned a null connection.");

}returnconn;

}}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值