来源 | 犀牛饲养员的技术笔记

封图| CSDN 下载于视觉中国

背景介绍

数据库连接池和线程池等池技术存在的意义都是为了解决资源的重复利用问题。在计算机里,创建一个新的资源往往开销是非常大的。而池技术可以统一分配,管理某一类资源,它允许我们的程序可以重复的使用这个资源,只有在极端情况下(比如连接池满)才会创建新的资源。

数据库连接这种资源尤其昂贵,它的创建开销很大,大量的创建连接和释放操作对程序的影响非常明显。

数据库连接池正是针对这个问题提出来的。

实现原理

需要注意的是,我们下面提供的几种实现方式都是基于简单的原型,目的是带你了解连接池实现的一些基本原理。真实的数据库连接池技术需要考虑更多复杂的细节。

所以下面这些代码都是不能在生产上直接使用的

实现的时候会用到java.sql.Connection,由于这个只是一个接口无法创建实例,为了演示方便,我继承这个接口写了一个简单的测试类,只是在commit方法里加了延时模拟提交。

实现方式1:

很容易马上想到的一种方案,我们用一个map存放连接对象,需要的时候从map里拿来用就可以了。

这里需要注意,尽管我们使用了线程安全的ConcurrentHashMap来存放连接资源,getConnection方法依然要加上synchronized关键字来避免并发问题。这一点是最容易忽略的。

试想一下,假设在某个场景下,我们希望某个应用的多个线程共享连接资源。

假设有2个线程同时执行到了pool.containsKey(key),然后都返回false,那这两个线程都会创建连接。虽然ConcurrentHashMap的put方法只会加入其中一个,但还是生成了1个多余的连接。

原因在于,尽管ConcurrentHashMap本身每个操作都是线程安全的,但是当这些操作组合在一起使用的时候,就无法保证原子性了,所以有可能带来并发的问题。

这里友情提示下,面试经常会遇到这个考点哦。

实现方式 2:

第二种实现方式是在1的基础上进行的优化。1的方案有个问题就是每次访问getConnection都要加锁,释放锁,效率比较低。

第二种方案是利用java并发包里的Future机制来解决并发场景创建多余连接的问题。

我们来捋一捋这个实现会不会有并发的问题。假设两个线程同时进入else分支,在代码的28行ConcurrentHashMap可以确保只有一个线程会执行,也就是只会加入一个task。其它的线程都不会加入成功。

所以只有一个线程connectionFutureTask == null,这个线程开始异步执行创建连接的任务,而其它的线程则会调用FutureTask的get方法直接获取结果。

实现方式3:

1和2的实现方式还存在一个问题, 多个线程获取到的其实同一个连接。这种方案在某些场景下是不允许的。比如spring数据库的事务管理器对于每个事务的处理线程都要求独立的连接资源。

下面的方案基于链表结构,有比较完整的获取,释放的操作,不同的线程可以拿到独立的连接资源。

注意到这个方案我们在获取连接的时候引入了超时时间,如果该方法能够在一段时间内获取到结果,那么将结果立刻返回,反之,超时返回默认结果。

druid连接池的实现原理

了解了实现连接池的大概思路,我们可以来继续学习下市面上比较成熟的连接池产品。这其中阿里巴巴开源的druid开源连接池就是一个代表。

Druid作为java领域最好的连接池技术之一,连接池本身只是它的一部分功能。除此之外,它还还要配套的监控功能。当然这个不是我们本文的重点。

先来看看在代码中如何使用Druid连接池,

所以继续深入到是DataSource里的getConnection方法,

init方法主要的功能是根据配置文件初始化连接池,它内部会生成一些真正的物理连接然后放入一个数组里。当然这个方法要保证只会被调用一次。

继续往下看,最终会调用到getConnectionInternal这个私有方法,

红色圈出的部分是核心,根据传入的等待时间走不同的分支,我们来看看takeLast方法。

代码逻辑也比较清楚,poolCount是连接池的目前的可用连接数量。

如果为0,就通过emptySignal唤醒生产者线程创建新的连接,同时当前线程挂起等待notEmpty的信号。notEmptyWaitCount维护的就是正在等待的消费者数量。

如果不为0,就从数组中取出最后一个连接返回。有人可能会有疑问,这里返回的是DruidConnectionHolder,不是Connection啊?

其实看下前者的定义你就明白了,

DruidConnectionHolder封装了Connection以及连接的datasource信息,还有多个statement等,方面进行统一管理。

参考

  • 《java并发编程的艺术》

  • https://www.cnblogs.com/cz123/p/7693064.html

推荐阅读:Docker 开发环境的滑坡
2020年边缘计算最新前沿报告:如何与核心云、5G、AI协同?如何打造新业态和部署运营?
教你用 Android 做二次开发,识别率达到科大讯飞语音输入水平 | 原力计划
比特币Logo背后有哪些历史及象征意义?Logo 上的“B”为什么会向右倾斜?
了解这4个重点,带你探索未来将如何设计智能系统和机器人!
苹果阻止上架的这款软件,到底有多可恶?
真香,朕在看了!

数据库连接池的原理没你想得这么复杂相关推荐

  1. 面试官:谈谈数据库连接池的原理

    来源:https://dwz.cn/oUF6pKOW 这次我们采取技术演进的方式来谈谈数据库连接池的技术出现过程及其原理,以及当下最流行的开源数据库连接池jar包. 一.早期我们怎么进行数据库操作 1 ...

  2. 3 连接sybase_今日头条面试官:给我说说数据库连接池的原理?

    作者:敦格 来源:https://urlify.cn/ABJbum 这次我们采取技术演进的方式来谈谈数据库连接池的技术出现过程及其原理,以及当下最流行的开源数据库连接池jar包. # 早期我们怎么进行 ...

  3. 谈谈数据库连接池的原理

    这次我们采取技术演进的方式来谈谈数据库连接池的技术出现过程及其原理,以及当下最流行的开源数据库连接池jar包. 一.早期我们怎么进行数据库操作        1.原理:一般来说,java应用程序访问数 ...

  4. java 连接池技术_java数据库连接池技术原理(浅析)

    在执行数据库SQL语句时,我们先要进行数据连接:而每次创建新的数据库的连接要消耗大量的资源,这样,大家就想出了数据库连接池技术.它的原理是,在运行过程中,同时打开着一定数量的数据库连接,形成数据连接池 ...

  5. Java数据库连接池实现原理

    https://blog.csdn.net/tuke_tuke/article/details/51532510 一般来说,Java应用程序访问数据库的过程是: ①装载数据库驱动程序: ②通过jdbc ...

  6. 【手写系列】理解数据库连接池底层原理之手写实现

    前言 数据库连接池的基本思想是:为数据库连接建立一个"缓冲池",预先在池中放入一定数量的数据库连接管道,需要时,从池子中取出管道进行使用,操作完毕后,再将管道放入池子中,从而避免了 ...

  7. 【MySQL】数据库连接池的原理及实现

    本专栏将从基础开始,循序渐进,讲解数据库的基本概念以及使用,希望大家都能够从中有所收获,也请大家多多支持. 专栏地址: 数据库必知必会 相关软件地址:软件地址 如果文章知识点有错误的地方,请指正!大家 ...

  8. 数据库连接池工作原理

    在实际应用开发中,特别是在WEB应用系统中,如果JSP.Servlet或EJB使用JDBC直接访问数据库中的数据,每一次数据访问请求都必须经历建立数据库连接.打开数据库.存取数据和关闭数据库连接等步骤 ...

  9. 说说数据库连接池工作原理和实现方案?

    **工作原理:**JAVA EE服务器启动时会建立一定数量的池连接,并一直维持不少于此数目的池连接.客户端程序需要连接时,池驱动程序会返回一个未使用的池连接并将其表记为忙.如果当前没有空闲连接,池驱动 ...

最新文章

  1. 百度搜索结果 转换_百度搜索搜不到“百度拦截搜索结果”
  2. maven安装、配置以及IDEA创建maven项目(Maven的Web项目)
  3. spark数据处理示例一:分类
  4. 电路常识性概念(1)-输入、输出阻抗
  5. css less 不要作用到子对象_CSS-预处理语言Sass、Less简述
  6. ajax传递json对象 php,PHP传递通过AJAX传递JSON对象数组到前台,前台解析,遍历JSON...
  7. 控制系统计算机仿真源码,控制系统计算机仿真-实验五.doc
  8. vue better-scroll 下拉上拉,加载刷新
  9. 《Java编程思想》学习笔记(一)——再度理解OOP
  10. Android 布局左中右布局
  11. 威纶触摸屏与三菱D700变频器485通讯程序 自己编写的威纶触摸屏与台达变频器的通讯程序
  12. UI自动化,元素被遮挡
  13. oracle索引b 树,oracle btree索引概述
  14. chrome 下载东西 失败禁止_chrome谷歌浏览器下载文件失败如何解决
  15. 利用软连接实现 OneDrive 任意文件夹同步
  16. 解码M3U8在线流视频AES-128解密TS合并到MP4
  17. 解决ImageView超出父控件(或屏幕边界)时,图片挤压问题
  18. 含有使字的诗句_古诗含“把”字
  19. Visual Paradigm社区版安装教程
  20. 你的磁力链为什么下不动了?(干货)

热门文章

  1. java jlist checkbox_JCheckBox检查Java中的JList中的切换逻辑时遇到问题
  2. 连接硬盘计算机没显示,新买的移动硬盘在我的电脑中无法显示,但是右下角图标显示已经连接,? 爱问知识人...
  3. java kcp,重新认识KCP - osc_rreaoxa0的个人空间 - OSCHINA - 中文开源技术交流社区
  4. php socket keepalive,linux keepalive探测对应用层socket api的影响
  5. 计算机组成原理刘红玲,计算机组成原理/21世纪高等学校规划教材
  6. 引用另一模板的宏_生信人值得拥有的编程模板Shell
  7. 与「韦神」齐名,他35岁任教清华!18岁一战成名,数学界颜值巅峰
  8. 吉林大学不如温州大学,泰晤士最新世界大学排名引发争议
  9. 当年赫赫有名的“四大工学院”,如今都发展得怎样?依然牛气冲天
  10. 前谷歌资深架构师:真正搞懂spring底层到底有什么好处?