Druid连接池源码解析(2)DruidDataSource-2

1 关闭连接池

关闭时调用close()方法,主要流程:

  • 依旧加锁,判断状态是初始化完成的,且没有关闭,进入关闭流程
  • 中断各个线程池
  • 从DruidConnectionHolder中获取连接,并依次关闭
  • 注销mbean,完成关闭流程,销毁Filter,释放锁

2 StackTrace

在DruidDataSource中单独定义了一个StackTrace,就是在初始化的时候获取了当前线程的StackTrace,目测目的是为了自定义输出调试信息

private String                           initStackTrace;
...
initStackTrace = Utils.toString(Thread.currentThread().getStackTrace());

3 重启连接池

重启时调用restart()方法,主要流程:
加锁->判断活跃连结数是否为0-> 调用close() ->调用resetStat()
resetStat()重置配置到默认值,设置各个原子计数器为0

        connectErrorCountUpdater.set(this, 0);
        errorCountUpdater.set(this, 0);
        commitCountUpdater.set(this, 0);
        rollbackCountUpdater.set(this, 0);
        startTransactionCountUpdater.set(this, 0);
        cachedPreparedStatementHitCountUpdater.set(this, 0);
        closedPreparedStatementCountUpdater.set(this, 0);
        preparedStatementCountUpdater.set(this, 0);
        transactionHistogram.reset();
        cachedPreparedStatementDeleteCountUpdater.set(this, 0);
        recycleErrorCountUpdater.set(this, 0);

        resetCountUpdater.incrementAndGet(this);
        //看起来比init多了几个计数器?

如果有配置变动,调用configFromPropety()重新配置各属性
此时重启便结束了,下一次调用getConnection()的时候,会调用init()重新初始化

4 其他细节

关于几个原子计数器,由于Druid说是为监控而生的连接池,默认是基于内存计数的,所以restart里清空的几个计数器,根据名字就能比较明显地知道是统计各种情况发生的次数的,如:链接错误数,事务提交、回滚数等等
那么之前init中的几个计数器,是做什么的么?
connectionIdSeedUpdater 追了下,主要是生成连接id的,对应到holder中的connectionId,
在DataSource中的getPoolingConnectionInfo(),放到了一个map里,缓存了连接信息
在DruidStatManagerFacade和DruidStatService 中获取了map中的连接信息,供监控控制台使用
dataSource的id本身是自增的,留出来的步长是生成connectionid等根据id的前缀判断属于哪个datasource

使用AtomicLongFieldUpdater的好处是:
因为当需要进行原子限定的属性所属的类会被创建大量的实例对象,如果用AtomicLong每个实例里面都要创建AtomicLong对象,从而多出内存消耗,使用AtomicLongFieldUpdater仅需要在抽象的父类中声明一个静态的更新器,就可以在各个对象中使用了。

你可能感兴趣的:(Druid连接池源码解析(2)DruidDataSource-2)