• DruidDataSource源码分析


    最近公司要求基于阿里的DruidDataSource来做一个连接池监控 , 正好之前没有看过DruidDataSource的源码 , 便自己看了四个多小时写了一些自己的理解 , 给大家分享一下 , 如果有什么错误 , 欢迎指出!!!

    DruidDataSource主要用到的是ReentrantLock锁,还有 notEmpty empty两个条件,生产连接与消费连接的线程在两个条件上等待与唤醒。


    1创建连接

        连接太多了的时候,在empty条件上等待,就是等空了再运行

     1 // 防止创建超过maxActive数量的连接
     2 if (activeCount + poolingCount >= maxActive) {
     3     empty.await();
     4     continue;
     5 }
     6 
     7 connection = createPhysicalConnection();
     8 setFailContinuous(false);
     9 
    10 boolean result = put(connection);


        后面是创建一个物理连接,然后put一下,这个put是放池子中,主要下面几句:

    1 holder = new DruidConnectionHolder(DruidDataSource.this, physicalConnectionInfo);
    2 connections[poolingCount] = holder;
    3 incrementPoolingCount();
    4 notEmpty.signal();
    5 notEmptySignalCount++;

       
    2使用连接

        DruidConnectionHolder takeLast()之中,当poolingCount中数量为0时等待。
        正好说明使用连接的线程,当连接没有时,就等待。如果池中有连接就执行下面的语句:

    1 decrementPoolingCount();
    2 DruidConnectionHolder last = connections[poolingCount];//拿走池中最后一个
    3 connections[poolingCount] = null;//最后一个赋值成null


        获取链接的主要方法getPooledConnection()中调用takeLast(),又调用getConnection(),
        这里面又是插入了过滤链来统计。filterChain.dataSource_connect()参数中有this,说明它把自己传进去了,
        说明这个filterChain并不从属于任何datasource,可以是这个数据源,也可以是那个数据源。具体过滤哪个,临时传入。

        
    3减少连接

        在创建连接线程附近还有一个DestroyConnectionThread()
        跟踪里面,有destroyTask.run();----->shrink(true);连接空闲的太多了就缩小。

        在shrink()方法中,重点有下面的语句:

    1 final int checkCount = poolingCount - minIdle;//池中的数量-最小空闲数量
    2     
    3 for (DruidConnectionHolder item : evictList) {//可回收的DruidConnectionHolder
    4     Connection connection = item.getConnection();
    5     JdbcUtils.close(connection);
    6     destroyCount.incrementAndGet();
    7 }


    4init()

        创建线程与收缩线程都是由void init()来调用的,主要代码如下。
       

     1 connections = new DruidConnectionHolder[maxActive];//新建连接池,个数是最大活动连接数maxActive。
     2 
     3 for (int i = 0, size = getInitialSize(); i < size; ++i) {//放入连接池中连接
     4     PhysicalConnectionInfo pyConnectInfo = createPhysicalConnection();
     5     DruidConnectionHolder holder = new DruidConnectionHolder(this, pyConnectInfo);
     6     connections[poolingCount] = holder;
     7     incrementPoolingCount();
     8 }
     9 
    10 createAndLogThread();
    11 createAndStartCreatorThread();//创建连接的线程,一直在工作,池子满了就是等待状态。
    12 createAndStartDestroyThread();//收缩池子的线程,一直在工作。
    13 
    14 
    15 initedLatch.await();//主线程在计数器为0前一直等待。
    16 
    17 init = true;


        这里有一个知识点。

    1 CountDownLatch initedLatch = new CountDownLatch(2); 

            就叫倒计时同步器。当前同步数为2,在变成0后,主线程才能运行,否则一直等待中。
            在创建连接与收缩池子的线程中都有initedLatch.countDown();,
            一共正好两个,主线程就是等待上面两个线程都运行了才运行,才置init状态标识为true。


  • 相关阅读:
    02.创建型————工厂方法模式
    01.创建型————简单工厂模式
    HBase JavaAPI操作示例
    MongoDB
    大数据第三天
    Zookeeper操作
    MR操作
    HDFS操作
    【GISER&&Painter】svg的那些事
    读法克鸡丝博文《技术,产品,团队》有感
  • 原文地址:https://www.cnblogs.com/wanghuijie/p/druiddatasource.html
Copyright © 2020-2023  润新知