Druid源码分析(四)-- 初始化DataSource3

10 篇文章 1 订阅

Druid源码分析(四)-- 初始化DataSource3

Druid源码分析(四)-- 初始化DataSource3

连接池

昨天分析了 filter 和 SPI 机制,今天接着往下看源码

// DruidDataSource.java#init()
// 连接池
connections = new DruidConnectionHolder[maxActive];
// 被断开的连接池
evictConnections = new DruidConnectionHolder[maxActive];
// 还正常的连接池
keepAliveConnections = new DruidConnectionHolder[maxActive]

这一段就是数据库连接池的初始化,maxActive是最大连接池数量
DruidConnectionHolder 包装了数据源和真正的数据库连接conn

// DruidConnectionHolder.java
// 数据源
protected final DruidAbstractDataSource       dataSource;
// 连接id
protected final long                          connectionId;
// 数据库连接
protected final Connection                    conn;

接着往下是连接池的初始化

// 如果是异步初始化,先初始化默认连接数,这个值默认为0
if (createScheduler != null && asyncInit) {
   for (int i = 0; i < initialSize; ++i) {
        submitCreateTask(true);
    }
} else if (!asyncInit) {
    // 初始化连接
    while (poolingCount < initialSize) {
        try {
            PhysicalConnectionInfo pyConnectInfo = createPhysicalConnection();
            DruidConnectionHolder holder = new DruidConnectionHolder(this, pyConnectInfo);
            connections[poolingCount++] = holder;
        } catch (SQLException ex) {
            ...
            // 异常就睡眠3s
            Thread.sleep(3000);
        }
    }
	...
}

接下来是创建日志线程和Create、Destroy线程,这里用到了CountDownLatch

createAndLogThread();
createAndStartCreatorThread();
createAndStartDestroyThread();

initedLatch.await();

// 默认initedLatch 为2
private final CountDownLatch initedLatch = new CountDownLatch(2);
protected void createAndStartDestroyThread() {
     initedLatch.countDown();
     ...
}

protected void createAndStartCreatorThread() {
     ...
     initedLatch.countDown();
}

CountDownLatch主要有两个方法:countDown()和await()。countDown()方法用于使计数器减一,其一般是执行任务的线程调用,await()方法则使调用该方法的线程处于等待状态,其一般是主线程调用。

接下来就是把初始化标识设置为true ,注册Mbean,添加JMX监控

init = true;
registerMbean();

最后,在finally里把初始化标识设置为true 、解锁,避免死锁

finally {
    inited = true;
    lock.unlock();
   if (init && LOG.isInfoEnabled()) {
       String msg = "{dataSource-" + this.getID();
       ...
        msg += "} inited";
        LOG.info(msg);
    } 

然后打印 {dataSource-1} inited
到这里整个 init 函数就完成了

总结

分析了3天的初始化函数,感觉学到了很多,不管是双重校验+锁,还是SPI机制、CountDownLatch等,我在日常项目里都没怎么用过,然后就是为了避免死锁等问题,一定要在finally 里解锁。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值