Druid连接池原理

article/2025/9/15 19:22:46

一、数据库连接池初始化

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

二、获取数据库连接

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

三、回收数据库连接

在这里插入图片描述
(1)、 在调用conn.close时候会回收当前连接到线程池

四、创建数据库连接线程

在这里插入图片描述
(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();}
}

http://chatgpt.dhexx.cn/article/muRSga4Q.shtml

相关文章

Druid之连接池

需要注意的是,我们下面提供的几种实现方式都是基于简单的原型,目的是带你了解连接池实现的一些基本原理。真实的数据库连接池技术需要考虑更多复杂的细节。 所以下面这些代码都是不能在生产上直接使用的。 实现的时候会用到java.sql.Connection&#x…

Druid连接池核心原理

一、什么是Druid连接池? Druid连接池是阿里巴巴开源的数据库连接池项目。Druid连接池为监控而生,内置强大的监控功能,监控特性不影响性能。功能强大,能防SQL注入,内置Loging能诊断Hack应用行为。 竞品对比 从上表可以…

德鲁伊连接池(druid)

文章目录 一、连接池1、什么是连接池2、为什么要用连接池 二、德鲁伊连接池(druid)1.介绍2.代码实操 一、连接池 1、什么是连接池 简单来说就是一组连接组成的一个池子(集合),称为连接池。 连接池是创建和管理一个连接的缓冲池技术。 2、为什么要用连…

【Druid 连接池】 学习~快速 掌握连接池基本原理

文章目录 前言提出问题:一、Druid连接池简述 再次提出问题 :二、初始化连接池三、了解三个核心成员(三大线程)四、获取连接五、探活(连接池连接健康的检查机制) 前言 翻遍了各个大佬发的博客整理出来的学习…

Druid连接池的基本配置与使用

Druid简介 Druid是阿里巴巴的开源连接池组件,是世界上最好的连接池之一。Druid能对数据库连接进行有效管理和重用,最大化程序执行的效率。连接池负责创建和管理连接,程序只负责取用与归还。 以下是我画的示意图: 下面我来给大家…

MySQL快捷键注释

MySQL语句注释快捷键显示为CtrlOemQuestion,对应于我们键盘上的是Ctrl?

Mysql 增加表注释

关注微信公共号:小程在线 关注CSDN博客:程志伟的博客 方法一: mysql添加表注释 ALTER TABLE 表名 COMMENT 注释字段; 实例: alter table test comment 测试表; 方法二: 在创建表的时候直接增加表注释…

mysql语句中的注释方法_MySQL语句注释方式简介

MySQL支持三种注释方式: 1.从‘#字符从行尾。 2.从‘-- 序列到行尾。请注意‘-- (双破折号)注释风格要求第2个破折号后面至少跟一个空格符(例如空格、tab、换行符等等)。 3.从/*序列到后面的*/序列。结束序列不一定在同一行中,因此该语法允许注释跨越多行…

MySQL注释:单行注释和多行注释,快进来理解

单行注释与多行注释 单行注释多行注释 单行注释 单行注释可以使用#注释符,#注释符后直接加注释内容 #注释内容单行注释可以使用- -注释符,- -注释符后需要加一个空格,注释才能生效。 -- 注释内容#和–的区别就是:#后面直接加注…

Mysql注释

Mysql注释 MySQL服务器支持3种注释风格: 从‘#’字符从行尾。 从‘-- ’序列到行尾。请注意‘-- ’(双破折号)注释风格要求第2个破折号后面至少跟一个空格符(例如空格、tab、换行符等等)。该语法与标准SQL注释语法稍有不同。 从/*序…

mysql注释乱码问题_mysql注释是中文乱码怎么办

mysql注释是中文乱码的解决办法:首先用“show variables like”命令查看数据库与服务端的字符集设置;然后执行语句为“set collation_serverutf8_general_ci;”即可。 mysql表注释乱码 问题 执行语句: alter table TABLE_XXX comment ‘中文号’; 结果: …

wepy开发小程序eslint报错error 'getApp' is not defined no-undef

wepy开发小程序使用getApp().globalData保存全局数据很方便,但是会在控制台看到很多报错:“error getApp is not defined no-undef”,这是eslint报错。 解决办法:在.eslintrc.js文件中加入 globals: { getApp: true } 转载于:ht…

微信小程序 关于获取用户信息的一种方法 “this.setData与getApp().globalData.userInfo“

获取用户信息&#xff1a;this.setData和getApp().globalData.userInfo; 最开始的WXML文件中&#xff0c;我们写下页面结构代码如下&#xff1a; <image class"userinfo-avatar" src"{{userInfo.avatarUrl}}" mode"cover"></image>…

JS交互逻辑——获取页面数据{{}}和全局数据const app = getApp()

JS交互逻辑 在小程序里边&#xff0c;我们就通过编写 JS 脚本文件来处理用户的操作 app.js中最外层需要App({}) &#xff0c;该函数是微信平台提供的api App({// 全局数据&#xff0c;可以在所有的子页面中使用mydata: {n: 100} }) // 页面获取全局数据的方式,app表示小程序的…

微信小程序getApp().globalData.user无法获取值

一、debug过程 在进行微信小程序的开发过程中&#xff0c;我利用如下代码获取全局变量中的username的值&#xff0c;但其结果缺如图中所示的只向数据库中存入了对应的类型即object Object。 username: getApp().globalData.user.username, 数据库结果 其中&#xff0c;全局变量…

微信小程序const app=getApp()的作用,实现page页面获取全局数据

app.js的作用 app.js是整个小程序项目的入口文件&#xff0c; 如果小程序要运行&#xff0c;第一个被执行的文件就是app.js&#xff0c;第一个被执行的代码是app.js中的onLaunch方法 在app.js中可以书写小程序的全局业务逻辑 在app.js里面&#xff0c;写上一些需要的东西&am…

uniapp中的getApp().globalDate.

获取全局变量&#xff1a; getApp().globalDate1.uni-app 在app.vue文件export default里面定义globalData&#xff0c;在其他文件则用getApp&#xff08;&#xff09;.globalData获取 2.在当前文件&#xff08;app.vue&#xff09;里面获取globalData需要用this.$options.glob…

解释微信小程序const app=getApp()的作用

const appgetApp()用来获取全局变量 const appgetApp()这就话通常在pages下的页面的js中写 来调用app.js中的globalData{} 直白一点说就是在app.js的globalData{}里写的东西 在其他页面的js的onshow中可以直接调用 例&#xff1a;

微信小程序 app=getApp()公共变量在页面间传值技巧。

1.公共变量 在开发过程中&#xff0c;避免不了会使用公共变量&#xff0c;记录共享对象状态、数据最简单的方式就是创建创建公共变量&#xff1b; 当业务逻辑变多&#xff0c;还采用这种思想就会变得危险&#xff0c;代码逻辑变得不清晰&#xff0c;慢慢就有一种代码坏味道。 …

【uniapp】uniapp的globalData以及getApp():

文章目录 一、说明文档&#xff1a;二、使用&#xff1a; 一、说明文档&#xff1a; 【官方文档】https://uniapp.dcloud.net.cn/collocation/App.html#globaldata 二、使用&#xff1a;