在初始化完三个存放连接的数组后,就是通过判断是否指定初始化连接个数判读是否创建连接了,暂时先不看。接着 druid 会启动三个守护线程:
createAndLogThread();
createAndStartCreatorThread();
createAndStartDestroyThread();
复制代码
第一个是打印连接池状态日志的线程,可通过设置 timeBetweenLogStatsMillis 小于 0 关闭。
第二个是创建连接的线程 CreateConnectionThread,里面通过一个 for (;;)的死循环,并且必须存在线程等待,才创建连接,否则线程就通过 empty.await()阻塞住。
第三个是创建销毁连接的线程 DestroyConnectionThread,里面也通过死循环不断的掉起 DestroyTask 任务,该任务通过 shrink 方法,对不同连接进行处理。
DruidConnectionHolder connection = connections[i];
if ((onFatalError || fatalErrorIncrement > 0) && (lastFatalErrorTimeMillis > connection.connectTimeMillis)) {
keepAliveConnections[keepAliveCount++] = connection;
continue;
}
if (checkTime) {
if (phyTimeoutMillis > 0) {
long phyConnectTimeMillis = currentTimeMillis - connection.connectTimeMillis;
if (phyConnectTimeMillis > phyTimeoutMillis) {
evictConnections[evictCount++] = connection;
continue;
}
}
long idleMillis = currentTimeMillis - connection.lastActiveTimeMillis;
if (idleMillis < minEvictableIdleTimeMillis
&& idleMillis < keepAliveBetweenTimeMillis
) {
break;
}
if (idleMillis >= minEvictableIdleTimeMillis) {
if (checkTime && i < checkCount) {
evictConnections[evictCount++] = connection;
continue;
} else if (idleMillis > maxEvictableIdleTimeMillis) {
evictConnections[evictCount++] = connection;
continue;
}
}
if (keepAlive && idleMillis >= keepAliveBetweenTimeMillis) {
keepAliveConnections[keepAliveCount++] = connection;
}
} else {
if (i < checkCount) {
evictConnections[evictCount++] = connection;
} else {
break;
}
}
复制代码
大致的思路是把有需要进行检查的连接放入 keepAliveConnections 数组中,包括有报错的连接,空闲时间超过设定的 keepAliveBetweenTimeMillis 的连接,把大于最小连接数并且空闲时间超过 minEvictableIdleTimeMillis 的连接放入 evictConnections 数组中。
接下来就遍历 evictConnections 数组,关闭其中连接,对 keepAliveConnections 数组中的连接检查可用性,可用的放回连接池,不可用的关闭掉。在连接池中线小于 minIdle 后,使用 emptySignal(),增加新连接。
在创建完三个守护线程后,使用了 initedLatch.await()阻塞主线程,可以看到在 CreateConnectionThread 和 DestroyConnectionThread 中,分别使用了 initedLatch.countDown();信号量来确保两个线程已经启动起来了。
初始化好之后就会将 dataSource 注册为一个 MBean,方便通过 JMX 进行管理。
到这里,init()方法就结束,之后是获取连接。
评论