当前位置: 首页 > news >正文

手写数据库连接池

数据库连接是个耗时操作.对数据库连接的高效管理影响应用程序的性能指标.

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

数据库连接池负责分配,管理和释放数据库连接.它允许应用程序重复使用一个现有的数据路连接,而不需要每次重新建立一个新的连接,利用数据库连接池将明显提升对数据库操作的性能.

数据库连接池技术方案:

1.C3P0

2.DBCP

3.Proxool

4.Tomcat jdbc Oppl

5.BoneCP

6.Druid

7.HikariCP

数据库连接池属于一种池化技术:

常见的有:http访问(httpclient),redis访问(redisPool),线程(线程池)等

新建个空项目

可能是版本原因idea创建空项目总要重启一下

设置下maven和encoding

新建模块

DataSource是JDK里的规范,用来专门放连接的.是一个连接工厂

自定义一个接口

里面需要实现的两个方法是:  其他的父接口的其他方式可以暂时不管

这样基础结构就有了

package com.pool;import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;/*** @author hrui* @date 2023/9/10 3:06*/
public class MyAbstractDataSource implements MyDataSourceInterface{private String url;private String driver;private String username;private String password;//最大的连接数量private int poolMaxActiveConnection=10;//最大空闲连接数private int poolMaxIdIeConnection=5;//当连接都在使用时候,最大检出时间(等待时间),毫秒private int poolTimeToWait=20000;public int getPoolMaxActiveConnection() {return poolMaxActiveConnection;}public void setPoolMaxActiveConnection(int poolMaxActiveConnection) {this.poolMaxActiveConnection = poolMaxActiveConnection;}public int getPoolMaxIdIeConnection() {return poolMaxIdIeConnection;}public void setPoolMaxIdIeConnection(int poolMaxIdIeConnection) {this.poolMaxIdIeConnection = poolMaxIdIeConnection;}public int getPoolTimeToWait() {return poolTimeToWait;}public void setPoolTimeToWait(int poolTimeToWait) {this.poolTimeToWait = poolTimeToWait;}public String getUrl() {return url;}public void setUrl(String url) {this.url = url;}public String getDriver() {return driver;}public void setDriver(String driver) {this.driver = driver;}public String getUsername() {return username;}public void setUsername(String username) {this.username = username;}public String getPassword() {return password;}public void setPassword(String password) {this.password = password;}@Overridepublic Connection getConnection() throws SQLException {return getConnection(username,password);}@Overridepublic Connection getConnection(String username, String password) throws SQLException {return doGetConnection(username,password);}private Connection doGetConnection(String username, String password) throws SQLException {Connection connection = DriverManager.getConnection(url, username, password);return connection;}
}

上面三个方法,都是获得连接

下面用动态代理方式实现对数据库连接的代理

package com.pool;import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.sql.Connection;/*** 采用动态代理实现对数据库连接的代理* @author hrui* @date 2023/9/10 3:45*/
public  class ConnectionProxy implements InvocationHandler {//真正连接private Connection realConnection;//代理连接private Connection proxyConnection;//数据源对象private MyDataSource myDataSource;public ConnectionProxy(Connection realConnection, MyDataSource myDataSource) {//初始化真实连接和数据源this.realConnection = realConnection;this.myDataSource = myDataSource;//初始化代理连接...需要一个代理对象  JDK动态代理this.proxyConnection= (Connection)Proxy.newProxyInstance(Connection.class.getClassLoader(),new Class<?>[]{Connection.class},this);}public Connection getRealConnection() {return realConnection;}public void setRealConnection(Connection realConnection) {this.realConnection = realConnection;}public Connection getProxyConnection() {return proxyConnection;}public void setProxyConnection(Connection proxyConnection) {this.proxyConnection = proxyConnection;}public MyDataSource getMyDataSource() {return myDataSource;}public void setMyDataSource(MyDataSource myDataSource) {this.myDataSource = myDataSource;}/*** 当调用Connection对象里面的任何方法时,该方法会进行拦截* 主要目的为了拦截Connection的close方法,当关闭时进行拦截,将Connection对象放入连接池中* 其他方法无需拦截* @param proxy* @param method* @param args* @return* @throws Throwable*/@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {//获取当前调用了Connection对象的什么方法String methodName=method.getName();if(methodName.equals("close")){//TODO 把连接放入连接池return null;}else{//其他方法return method.invoke(realConnection, args);}}
}}

下面写个类继承MyAbstractDataSource  在里面放入连接池

package com.pool;import java.sql.Connection;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;/*** 数据源连接池* @author hrui* @date 2023/9/10 4:15*/
public class MyDataSource extends MyAbstractDataSource{//空闲连接private final List<ConnectionProxy> idleConnections=new ArrayList<>();//激活的连接池private final List<ConnectionProxy> activeConnections=new ArrayList<>();//下面三个可以抽取放到父类抽象类中,由用户配置 //最大的连接数量//private int poolMaxActiveConnection=10;//最大空闲连接数//private int poolMaxIdIeConnection=5;//当连接都在使用时候,最大检出时间(等待时间),毫秒//private int poolTimeToWait=20000;//用于同步监视器对象private final Object monitor=new Object();//用于同步监视器对象(关闭)//private final Object watch=new Object();/*** 重写:用于获取代理连接* @return* @throws SQLException*/@Overridepublic Connection getConnection() throws SQLException {ConnectionProxy connectionProxy=getConnectionProxy(super.getUsername(),super.getPassword());//返回代理连接return super.getConnection();}/*** 获取代理连接* @param username* @param password* @return*/private ConnectionProxy getConnectionProxy(String username,String password) throws SQLException {//TODO//是否需要等待boolean wait=false;ConnectionProxy connectionProxy=null;//刚开始没有连接while(connectionProxy==null){synchronized (monitor){//看连接池有没有空闲连接,如果不为空,直接获取连接if(!idleConnections.isEmpty()){connectionProxy=idleConnections.remove(0);//如果是空的}else{//没有空闲连接,那么需要获取新的连接(创建连接)//这里先判断最大连接数是不是小于配置数量  10if(activeConnections.size()<supper.getPoolMaxActiveConnection()){//创建新连接  需要传入真实连接connectionProxy=new ConnectionProxy(super.getConnection(),this);}//否则需要等待20秒   上面定义了poolTimeToWait=20000}}if(!wait){wait=true;}if(connectionProxy==null){try {monitor.wait(supper.getPoolTimeToWait());} catch (InterruptedException e) {e.printStackTrace();//万一等待被线程打断,退出一下break;}}}if(connectionProxy!=null){//连接对象不是空,说明已经拿到连接了,放入容器activeConnections.add(connectionProxy);}return connectionProxy;}//用于关连接//不是把连接关系,而是还给连接池public void closeConnection(ConnectionProxy connectionProxy){synchronized (monitor){//最大连接(激活连接)里删除activeConnections.remove(connectionProxy);//如果空闲连接<定义的数量则放入空闲连接if(idleConnections.size()<supper.getPoolMaxIdIeConnection()){idleConnections.add(connectionProxy);}//通知一下,唤醒上面哪个等待获取连接的线程monitor.notify();}}
}

那么代理对象中把连接还给连接池的方法也有了

就是当所有连接用完了,等待20秒的逻辑没写

下面测试自己写的连接池

新建模块  引入依赖

不想玩了

相关文章:

手写数据库连接池

数据库连接是个耗时操作.对数据库连接的高效管理影响应用程序的性能指标. 数据库连接池正是针对这个问题提出来的. 数据库连接池负责分配,管理和释放数据库连接.它允许应用程序重复使用一个现有的数据路连接,而不需要每次重新建立一个新的连接,利用数据库连接池将明显提升对数…...

在CentOS7上增加swap空间

在CentOS7上增加swap空间 在CentOS7上增加swap空间&#xff0c;可以按照以下步骤进行操作&#xff1a; 使用以下命令检查当前swap使用情况&#xff1a; swapon --show创建一个新的swap文件。你可以根据需要指定大小。例如&#xff0c;要创建一个2GB的swap文件&#xff0c;使用…...

@Autowired和@Resource

文章目录 简介Autowired注解什么是Autowired注解Autowired注解的使用方式Autowired注解的优势和不足 Qualifier总结&#xff1a; Resource注解什么是Resource注解Resource注解的使用方式Resource注解的优势和不足 Autowired vs ResourceAutowired和Resource的区别为什么推荐使用…...

QTableView通过setColumnWidth设置了列宽无效的问题

在用到QT的QTableView时&#xff0c;为了显示效果&#xff0c;向手动的设置每一列的宽度&#xff0c;但是如下的代码是无效的。 ui->tableView->setColumnWidth(0,150);ui->tableView->setColumnWidth(1,150);ui->tableView->setColumnWidth(2,150);ui->t…...

【用unity实现100个游戏之10】复刻经典俄罗斯方块游戏

文章目录 前言开始项目网格生成Block方块脚本俄罗斯方块基类&#xff0c;绘制方块形状移动逻辑限制移动自由下落下落后设置对应风格为不可移动类型检查当前方块是否可以向指定方向移动旋转逻辑消除逻辑游戏结束逻辑怪物生成源码参考完结 前言 当今游戏产业中&#xff0c;经典游…...

Docker容器内数据备份到系统本地

Docker运行容器时没将目录映射出来&#xff0c;或者因docker容器内外数据不一致&#xff0c;导致docker运行错误的&#xff0c;可以使用以下步骤处理&#xff1a; 1.进入要备份的容器&#xff1a; docker exec -it <容器名称或ID> /bin/bash2.在容器内创建一个临时目录…...

学信息系统项目管理师第4版系列06_项目管理概论

1. 项目基础 1.1. 项目是为创造独特的产品、服务或成果而进行的临时性工作 1.1.1. 独特的产品、服务或成果 1.1.2. 临时性工作 1.1.2.1. 项目有明确的起点和终点 1.1.2.2. 不一定意味着项目的持续时间短 1.1.2.3. 临时性是项目的特点&#xff0c;不是项目目标的特点 1.1…...

Java发送(QQ)邮箱、验证码发送

前言 使用Java应用程序发送 E-mail 十分简单&#xff0c;但是首先需要在项目中导入 JavaMail API 和Java Activation Framework (JAF) 的jar包。 菜鸟教程提供的下载链接&#xff1a; JavaMail mail.jar 1.4.5JAF&#xff08;版本 1.1.1&#xff09; activation.jar 1、准备…...

PostgresSQL----基于Kubernetes部署PostgresSQL

【PostgresSQL----基于Kubernetes部署PostgresSQL】 文章目录 一、创建SC、PV和PVC存储对象1.1 准备一个nfs服务器1.2 编写SC、PV、PVC等存储资源文件1.3 编写部署PostgresSQL数据库的资源声明文件 二、部署PostgresSQL2.1 部署 PV、PVC等存储对象2.2 部署PostgresSQL数据库2.3…...

7 个适合初学者的项目,可帮助您开始使用 ChatGPT

推荐&#xff1a;使用 NSDT场景编辑器快速搭建3D应用场景 从自动化日常任务到预测复杂模式&#xff0c;人工智能正在重塑行业并重新定义可能性。 当我们站在这场人工智能革命中时&#xff0c;我们必须了解它的潜力并将其整合到我们的日常工作流程中。 然而。。。我知道开始使…...

JDBC操作SQLite的工具类

直接调用无需拼装sql 注入依赖 <dependency><groupId>org.xerial</groupId><artifactId>sqlite-jdbc</artifactId><version>3.43.0.0</version></dependency>工具类 import org.sqlite.SQLiteConnection;/*** Author cpf* Dat…...

SEO百度优化基础知识全解析(了解百度SEO标签作用)

百度SEO优化的作用介绍&#xff1a; 百度SEO优化是指通过对网站的内部结构、外部链接、内容质量、用户体验等方面进行优化&#xff0c;提升网站在百度搜索结果中的排名&#xff0c;从而提高网站的曝光率和流量。通过百度SEO优化&#xff0c;可以让更多的潜在用户找到你的网站&…...

用python实现基本数据结构【03/4】

说明 如果需要用到这些知识却没有掌握&#xff0c;则会让人感到沮丧&#xff0c;也可能导致面试被拒。无论是花几天时间“突击”&#xff0c;还是利用零碎的时间持续学习&#xff0c;在数据结构上下点功夫都是值得的。那么Python 中有哪些数据结构呢&#xff1f;列表、字典、集…...

软件测试面试题汇总

测试技术面试题 软件测试面试时一份好简历的重要性 1、什么是兼容性测试&#xff1f;兼容性测试侧重哪些方面&#xff1f; 5 2、我现在有个程序&#xff0c;发现在Windows上运行得很慢&#xff0c;怎么判别是程序存在问题还是软硬件系统存在问题&#xff1f; 5 3、测试的策略…...

AP5101C 高压线性恒流IC 宽电压6-100V LED汽车大灯照明 台灯LED矿灯 指示灯电源驱动

产品描述 AP5101C 是一款高压线性 LED 恒流芯片 &#xff0c; 外围简单 、 内置功率管 &#xff0c; 适用于6- 100V 输入的高精度降压 LED 恒流驱动芯片。电流2.0A。AP5101C 可实现内置MOS 做 2.0A,外置 MOS 可做 3.0A 的。AP5101C 内置温度保护功能 &#xff0c;温度保护点为…...

【大数问题】字符串相减(大数相减)<模拟>

类似 【力扣】415. 字符串相加&#xff08;大数相加&#xff09;&#xff0c;实现大数相减。 题解 模拟相减的过程&#xff0c;先一直使大数减小数&#xff0c;记录借位&#xff0c;最后再判断是否加负号。&#xff08;中间需要删除前导0&#xff0c;例如10001-1000000001&am…...

easycode生成代码模板配置

实体&#xff1a; ##引入宏定义 $!define##使用宏定义设置回调&#xff08;保存位置与文件后缀&#xff09;$!autoImport import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; import lombok.NoArgsConstructor; i…...

【数据结构】堆排序和Top-k问题

【数据结构】堆 堆排序 如果只是将待排数组建立一个大堆或者小堆是无法得到一个升序或者降序的数组&#xff0c;因为对与一个堆&#xff0c;我们没法知道同一层的大小关系。 但是&#xff0c;如果建立了一个大堆&#xff0c;那么堆顶元素一定是这个数组中最大的&#xff0c;…...

经典的生产者和消费者模型问题

典型的生产者-消费者问题,可以使用 Java 中的 java.util.concurrent 包提供的 BlockingQueue 来实现。BlockingQueue 是一个线程安全的队列,它可以处理这种生产者-消费者的场景。以下是一个示例代码: import java.util.concurrent.ArrayBlockingQueue; import java.util.co…...

Java基础:代理

这里写目录标题 什么是代理1.静态代理&#xff08;委托类、代理类&#xff09;&#xff1a;使用步骤&#xff1a;示例优缺点 2.动态代理&#xff08;委托类、中介类&#xff09;2.1 JDK动态代理使用&#xff1a;中介类&#xff1a;示例1&#xff1a;示例2&#xff1a; 2.2 CGLi…...

STM32标准库-DMA直接存储器存取

文章目录 一、DMA1.1简介1.2存储器映像1.3DMA框图1.4DMA基本结构1.5DMA请求1.6数据宽度与对齐1.7数据转运DMA1.8ADC扫描模式DMA 二、数据转运DMA2.1接线图2.2代码2.3相关API 一、DMA 1.1简介 DMA&#xff08;Direct Memory Access&#xff09;直接存储器存取 DMA可以提供外设…...

【2025年】解决Burpsuite抓不到https包的问题

环境&#xff1a;windows11 burpsuite:2025.5 在抓取https网站时&#xff0c;burpsuite抓取不到https数据包&#xff0c;只显示&#xff1a; 解决该问题只需如下三个步骤&#xff1a; 1、浏览器中访问 http://burp 2、下载 CA certificate 证书 3、在设置--隐私与安全--…...

如何为服务器生成TLS证书

TLS&#xff08;Transport Layer Security&#xff09;证书是确保网络通信安全的重要手段&#xff0c;它通过加密技术保护传输的数据不被窃听和篡改。在服务器上配置TLS证书&#xff0c;可以使用户通过HTTPS协议安全地访问您的网站。本文将详细介绍如何在服务器上生成一个TLS证…...

HBuilderX安装(uni-app和小程序开发)

下载HBuilderX 访问官方网站&#xff1a;https://www.dcloud.io/hbuilderx.html 根据您的操作系统选择合适版本&#xff1a; Windows版&#xff08;推荐下载标准版&#xff09; Windows系统安装步骤 运行安装程序&#xff1a; 双击下载的.exe安装文件 如果出现安全提示&…...

WEB3全栈开发——面试专业技能点P2智能合约开发(Solidity)

一、Solidity合约开发 下面是 Solidity 合约开发 的概念、代码示例及讲解&#xff0c;适合用作学习或写简历项目背景说明。 &#x1f9e0; 一、概念简介&#xff1a;Solidity 合约开发 Solidity 是一种专门为 以太坊&#xff08;Ethereum&#xff09;平台编写智能合约的高级编…...

拉力测试cuda pytorch 把 4070显卡拉满

import torch import timedef stress_test_gpu(matrix_size16384, duration300):"""对GPU进行压力测试&#xff0c;通过持续的矩阵乘法来最大化GPU利用率参数:matrix_size: 矩阵维度大小&#xff0c;增大可提高计算复杂度duration: 测试持续时间&#xff08;秒&…...

安卓基础(aar)

重新设置java21的环境&#xff0c;临时设置 $env:JAVA_HOME "D:\Android Studio\jbr" 查看当前环境变量 JAVA_HOME 的值 echo $env:JAVA_HOME 构建ARR文件 ./gradlew :private-lib:assembleRelease 目录是这样的&#xff1a; MyApp/ ├── app/ …...

云原生玩法三问:构建自定义开发环境

云原生玩法三问&#xff1a;构建自定义开发环境 引言 临时运维一个古董项目&#xff0c;无文档&#xff0c;无环境&#xff0c;无交接人&#xff0c;俗称三无。 运行设备的环境老&#xff0c;本地环境版本高&#xff0c;ssh不过去。正好最近对 腾讯出品的云原生 cnb 感兴趣&…...

Linux C语言网络编程详细入门教程:如何一步步实现TCP服务端与客户端通信

文章目录 Linux C语言网络编程详细入门教程&#xff1a;如何一步步实现TCP服务端与客户端通信前言一、网络通信基础概念二、服务端与客户端的完整流程图解三、每一步的详细讲解和代码示例1. 创建Socket&#xff08;服务端和客户端都要&#xff09;2. 绑定本地地址和端口&#x…...

Git常用命令完全指南:从入门到精通

Git常用命令完全指南&#xff1a;从入门到精通 一、基础配置命令 1. 用户信息配置 # 设置全局用户名 git config --global user.name "你的名字"# 设置全局邮箱 git config --global user.email "你的邮箱example.com"# 查看所有配置 git config --list…...