在初始化完三个存放连接的数组后,就是通过判断是否指定初始化连接个数判读是否创建连接了,暂时先不看。接着 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()方法就结束,之后是获取连接。
评论