Druid连接池原理学习

翻了下之前记得笔记,发现有个对druid线程池的概要介绍,下面分析给大家

一、数据库连接池初始化

screenshot.png

(1)、 如果设置了maxWait或者构造函数参数传入的为true,则创建的ReentrantLock为公平锁,否者为非公平锁 (2)、 如果设置了initialSize>=1,则会启动是创建initialSize个数数据库物理连接到线程池。 (3)、 如果没设置createScheduler则创建并启动数据库连接创建线程,如果没设置destroyScheduler则创建并启动数据库连接回收线程,如果timeBetweenLogStatsMillis>0则创建logstat线程。

阿里巴巴长期招聘Java研发工程师p6,p7,p8等上不封顶级别,有意向的可以发简历给我,注明想去的部门和工作地点:1064454834@qq.com

二、获取数据库连接

screenshot.png

(1)、 如果当前数据库连接池有可用连接,则直接获取,否者如果设置createScheduler则开启一个新线程去创建物理连接,否者发送发送signal信号唤醒连接创建线程创建数据库物理连接,这种情况有分pollLast和takeLast,区别在于前者设置max wait超时时间,如果在时间内还没获取链接则返回null,后者则一直等待连接创建。

三、回收数据库连接

screenshot.png

(1)、 在调用conn.close时候会回收当前连接到线程池

四、创建数据库连接线程

screenshot.png

(1)、此图createScheduler=null的情况,为null从上面知道在初始化时候会新建 一个数据库连接创建线程。

五、连接池同步策略

实际上是个生产者消费者模式,生产者是连接创建线程和连接回收线程,消费者是获取连接的线程。 首先列下同步需要的条件变量和锁:

 //独占锁(用来控制同是只有一个线程访问线程池),根据lockFair分为公平和非公平锁
 lock     = new ReentrantLock(lockFair);
 
 //用来对消费和生成线程做同步
 notEmpty = lock.newCondition();
 empty    = lock.newCondition();
 
 //共享资源,线程池是一个数组
 connections = new DruidConnectionHolder[maxActive];

消费者(获取数据库连接线程):

DruidConnectionHolder pollLast(){
    
    DruidConnectionHolder holder;

    try {
            //加独占锁
            lock.lockInterruptibly();
        } catch (InterruptedException e) {
            connectErrorCount.incrementAndGet();
            throw new SQLException("interrupt", e);
    }

    try {

        //通知连接创建线程,创建数据库连接
        empty.signal();

        //等待连接创建线程或者连接回收线程发送信号
        estimate = notEmpty.awaitNanos(estimate);

        //获取链接,并返回
        decrementPoolingCount();
        holder = connections[poolingCount];
        connections[poolingCount] = null;
   

    }finally{
        //释放独占锁
        lock.unlock();

    }


    holder.incrementUseCount();
    DruidPooledConnection poolalbeConnection = new DruidPooledConnection(holder);

    return poolalbeConnection;
}

生产者(连接创建线程):

public void run(){
    try {
        //独占锁
        lock.lockInterruptibly();
    } catch (InterruptedException e2) {
        break;
    }

    try {
        // 必须存在线程等待,才创建连接
        if (poolingCount >= notEmptyWaitThreadCount) {
            empty.await();//会释放当前独占锁

        }

        // 防止创建超过maxActive数量的连接
        if (activeCount + poolingCount >= maxActive) {
            empty.await();//会释放当前独占锁
        }
    } finally {
        lock.unlock();
    }

    Connection connection = null;

    try {
        //创建物理链接
        connection = createPhysicalConnection();
    } catch (SQLException e) {
        。。。。
    } catch (RuntimeException e) {
        。。。。
    } catch (Error e) {
        。。。。
    }


    lock.lock();
    try {
        //连接入池
        connections[poolingCount] = holder;
        incrementPoolingCount();

        if (poolingCount > poolingPeak) {
            poolingPeak = poolingCount;
            poolingPeakTime = System.currentTimeMillis();
        }

        //发出信号,激活消费线程
        notEmpty.signal();
        notEmptySignalCount++;

    } finally {
        lock.unlock();
    }


}

生产者(数据库连接回收线程):

protected void recycle(DruidPooledConnection pooledConnection){
    lock.lockInterruptibly();
    try {
        activeCount--;
        closeCount++;

        connections[poolingCount] = e;
        incrementPoolingCount();

        if (poolingCount > poolingPeak) {
            poolingPeak = poolingCount;
            poolingPeakTime = lastActiveTimeMillis;
        }

        //激活消费线程
        notEmpty.signal();
        notEmptySignalCount++;      
        recycleCount++;
    } finally {
        lock.unlock();
    }
}

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏北京马哥教育

万字长文带你OpenStack从入门到放弃

1934
来自专栏龙首琴剑庐

基于复杂方案OWSAP CsrfGuard的CSRF安全解决方案(适配nginx + DWR)

1、什么是CSRF? 已经有很多博文讲解其过程和攻击手段,在此就不重复了。 O(∩_∩)O 不清楚的同学,请自行搜索或按链接去了解: http://blog...

4657
来自专栏静晴轩

如何设置添加SSH

去(2014)年有开始折腾个人Blog;从使用Jekll到Hexo,平台也从Github一度迁移至国内的Gitcafe(Hexo创建/测试/发布Blog都极为方...

5116
来自专栏源码之家

一键安装桌面及VNC

5276
来自专栏西安-晁州

小程序开发知识点总结

我承认,最近比较懒了,博客也很久没更新了,太对不住自己了,做了一段时间小程序开发,总结了一些知识点,直接上菜。

2261
来自专栏前端萌媛的成长之路

一波webpack

1864
来自专栏知识分享

轻松使用8266

今天算是做好了板子啦!做了一块直接用串口配置8266的板子,,也可以无线配置,配置完一次,上电自动运行...这篇文章也是写给一个朋友看的,朋友的项目做了很长时间...

3499
来自专栏前端杂货铺

使用ETag进行session的降级

回顾 在web后台开发中我们经常需要存储一些变量到session中进行暂存,最为特殊的就是“购物车”,由于http的无状态特性,因此我们需要在客户端打上一个标记...

4016
来自专栏漫漫前端路

前端安全知识

xss: 跨站脚本攻击(Cross Site Scripting)是最常见和基本的攻击 WEB 网站方法,攻击者通过注入非法的 html 标签或者 javasc...

1052
来自专栏pythonlove

Linux防火墙iptables(二)

上一篇文章我们说了一些iptables/netfilter的基础知识,本文我们来介绍一下iptables的规则编写。Iptables的规则可以概括的分为两个方面...

2782

扫码关注云+社区

领取腾讯云代金券