Druid-代码段-3-1
本代码段对应主流程3,新增连接的守护线程:
//DruidDataSource的内部类,对应主流程3,用来补充连接
public class CreateConnectionThread extends Thread {
public CreateConnectionThread(String name){
super(name); //重置线程名称
this.setDaemon(true); //标记为守护线程
}
//run方法
public void run() {
initedLatch.countDown(); //通知init(主流程2)自己已经启动成功
long lastDiscardCount = 0;
int errorCount = 0;
for (;;) { //死循环
// addLast
try {
lock.lockInterruptibly(); //锁获取
} catch (InterruptedException e2) {
break;
}
long discardCount = DruidDataSource.this.discardCount;
//当前丢弃连接数与最后一次丢弃连接数的差值大于0,说明又发生了丢弃连接的现象,该条件会促进连接的创建
boolean discardChanged = discardCount - lastDiscardCount > 0;
lastDiscardCount = discardCount;
try {
boolean emptyWait = true;
if (createError != null
&& poolingCount == 0
&& !discardChanged) {
emptyWait = false;
}
if (emptyWait
&& asyncInit && createCount < initialSize) {
emptyWait = false;
}
if (emptyWait) {
// 必须存在线程等待,才创建连接,否则不创建
if (poolingCount >= notEmptyWaitThreadCount
&& (!(keepAlive && activeCount + poolingCount < minIdle))
&& !isFailContinuous()
) {
empty.await(); //不需要创建连接时,阻塞(挂起)
}
// 防止创建超过maxActive数量的连接
if (activeCount + poolingCount >= maxActive) {
empty.await(); //超出限制依然挂起,不再新增连接
continue;
}
}
} catch (InterruptedException e) {
lastCreateError = e;
lastErrorTimeMillis = System.currentTimeMillis();
if (!closing) {
LOG.error("create connection Thread Interrupted, url: " + jdbcUrl, e);
}
break;
} finally {
lock.unlock(); //锁释放
}
//从上面的程序走到这里,说明该线程被成功唤起,则进行新建连接
PhysicalConnectionInfo connection = null;
try {
connection = createPhysicalConnection(); //利用驱动程序新建物理连接
} catch (SQLException e) {
LOG.error("create connection SQLException, url: " + jdbcUrl + ", errorCode " + e.getErrorCode()
+ ", state " + e.getSQLState(), e);
errorCount++;
if (errorCount > connectionErrorRetryAttempts && timeBetweenConnectErrorMillis > 0) {
// fail over retry attempts
setFailContinuous(true);
if (failFast) {
lock.lock();
try {
notEmpty.signalAll();
} finally {
lock.unlock();
}
}
if (breakAfterAcquireFailure) {
break;
}
try {
Thread.sleep(timeBetweenConnectErrorMillis);
} catch (InterruptedException interruptEx) {
break;
}
}
} catch (RuntimeException e) {
LOG.error("create connection RuntimeException", e);
setFailContinuous(true);
continue;
} catch (Error e) {
LOG.error("create connection Error", e);
setFailContinuous(true);
break;
}
if (connection == null) {
continue; //新建失败后再次尝试
}
boolean result = put(connection); //尝试放入池子
if (!result) {
JdbcUtils.close(connection.getPhysicalConnection());
LOG.info("put physical connection to pool failed.");
}
errorCount = 0; // reset errorCount
}
}
}
//这一个put方法是上面触发接收PhysicalConnectionInfo类型连接用的,之前说过,最终保存在池子里的连接对象都是DruidConnectionHolder类型,所以这里时进行一次包装,然后真正put进去的是更下面的put方法
protected boolean put(PhysicalConnectionInfo physicalConnectionInfo) {
DruidConnectionHolder holder = null;
try {
//包装成holder类型
holder = new DruidConnectionHolder(DruidDataSource.this, physicalConnectionInfo);
} catch (SQLException ex) {
lock.lock();
try {
if (createScheduler != null) {
createTaskCount--;
}
} finally {
lock.unlock();
}
LOG.error("create connection holder error", ex);
return false;
}
return put(holder); //真正放入池子
}
//真正将连接对象放入池子
private boolean put(DruidConnectionHolder holder) {
lock.lock();
try {
if (poolingCount >= maxActive) {
return false; //如果此时发现当前池子里的闲置连接数已经超过了maxActive,那么就不再往里面加了
}
connections[poolingCount] = holder; //加在数组尾部
incrementPoolingCount(); //poolingCount++
if (poolingCount > poolingPeak) {
poolingPeak = poolingCount;
poolingPeakTime = System.currentTimeMillis();
}
notEmpty.signal(); //唤起一个因为拿不到连接对象而发生阻塞的业务线程,让其再次进入运行状态,进行获取连接竞争
notEmptySignalCount++;
if (createScheduler != null) { //模式未启用
createTaskCount--;
if (poolingCount + createTaskCount < notEmptyWaitThreadCount //
&& activeCount + poolingCount + createTaskCount < maxActive) {
emptySignal();
}
}
} finally {
lock.unlock();
}
return true;
}