手写数据库连接池
数据库连接是个耗时操作.对数据库连接的高效管理影响应用程序的性能指标.
数据库连接池正是针对这个问题提出来的.
数据库连接池负责分配,管理和释放数据库连接.它允许应用程序重复使用一个现有的数据路连接,而不需要每次重新建立一个新的连接,利用数据库连接池将明显提升对数据库操作的性能.
数据库连接池技术方案:
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空间,可以按照以下步骤进行操作: 使用以下命令检查当前swap使用情况: swapon --show创建一个新的swap文件。你可以根据需要指定大小。例如,要创建一个2GB的swap文件,使用…...

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

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

【用unity实现100个游戏之10】复刻经典俄罗斯方块游戏
文章目录 前言开始项目网格生成Block方块脚本俄罗斯方块基类,绘制方块形状移动逻辑限制移动自由下落下落后设置对应风格为不可移动类型检查当前方块是否可以向指定方向移动旋转逻辑消除逻辑游戏结束逻辑怪物生成源码参考完结 前言 当今游戏产业中,经典游…...
Docker容器内数据备份到系统本地
Docker运行容器时没将目录映射出来,或者因docker容器内外数据不一致,导致docker运行错误的,可以使用以下步骤处理: 1.进入要备份的容器: 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. 临时性是项目的特点,不是项目目标的特点 1.1…...

Java发送(QQ)邮箱、验证码发送
前言 使用Java应用程序发送 E-mail 十分简单,但是首先需要在项目中导入 JavaMail API 和Java Activation Framework (JAF) 的jar包。 菜鸟教程提供的下载链接: JavaMail mail.jar 1.4.5JAF(版本 1.1.1) 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
推荐:使用 NSDT场景编辑器快速搭建3D应用场景 从自动化日常任务到预测复杂模式,人工智能正在重塑行业并重新定义可能性。 当我们站在这场人工智能革命中时,我们必须了解它的潜力并将其整合到我们的日常工作流程中。 然而。。。我知道开始使…...
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优化的作用介绍: 百度SEO优化是指通过对网站的内部结构、外部链接、内容质量、用户体验等方面进行优化,提升网站在百度搜索结果中的排名,从而提高网站的曝光率和流量。通过百度SEO优化,可以让更多的潜在用户找到你的网站&…...

用python实现基本数据结构【03/4】
说明 如果需要用到这些知识却没有掌握,则会让人感到沮丧,也可能导致面试被拒。无论是花几天时间“突击”,还是利用零碎的时间持续学习,在数据结构上下点功夫都是值得的。那么Python 中有哪些数据结构呢?列表、字典、集…...
软件测试面试题汇总
测试技术面试题 软件测试面试时一份好简历的重要性 1、什么是兼容性测试?兼容性测试侧重哪些方面? 5 2、我现在有个程序,发现在Windows上运行得很慢,怎么判别是程序存在问题还是软硬件系统存在问题? 5 3、测试的策略…...

AP5101C 高压线性恒流IC 宽电压6-100V LED汽车大灯照明 台灯LED矿灯 指示灯电源驱动
产品描述 AP5101C 是一款高压线性 LED 恒流芯片 , 外围简单 、 内置功率管 , 适用于6- 100V 输入的高精度降压 LED 恒流驱动芯片。电流2.0A。AP5101C 可实现内置MOS 做 2.0A,外置 MOS 可做 3.0A 的。AP5101C 内置温度保护功能 ,温度保护点为…...
【大数问题】字符串相减(大数相减)<模拟>
类似 【力扣】415. 字符串相加(大数相加),实现大数相减。 题解 模拟相减的过程,先一直使大数减小数,记录借位,最后再判断是否加负号。(中间需要删除前导0,例如10001-1000000001&am…...
easycode生成代码模板配置
实体: ##引入宏定义 $!define##使用宏定义设置回调(保存位置与文件后缀)$!autoImport import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; import lombok.NoArgsConstructor; i…...

【数据结构】堆排序和Top-k问题
【数据结构】堆 堆排序 如果只是将待排数组建立一个大堆或者小堆是无法得到一个升序或者降序的数组,因为对与一个堆,我们没法知道同一层的大小关系。 但是,如果建立了一个大堆,那么堆顶元素一定是这个数组中最大的,…...
经典的生产者和消费者模型问题
典型的生产者-消费者问题,可以使用 Java 中的 java.util.concurrent 包提供的 BlockingQueue 来实现。BlockingQueue 是一个线程安全的队列,它可以处理这种生产者-消费者的场景。以下是一个示例代码: import java.util.concurrent.ArrayBlockingQueue; import java.util.co…...
Java基础:代理
这里写目录标题 什么是代理1.静态代理(委托类、代理类):使用步骤:示例优缺点 2.动态代理(委托类、中介类)2.1 JDK动态代理使用:中介类:示例1:示例2: 2.2 CGLi…...

智慧医疗能源事业线深度画像分析(上)
引言 医疗行业作为现代社会的关键基础设施,其能源消耗与环境影响正日益受到关注。随着全球"双碳"目标的推进和可持续发展理念的深入,智慧医疗能源事业线应运而生,致力于通过创新技术与管理方案,重构医疗领域的能源使用模式。这一事业线融合了能源管理、可持续发…...

前端导出带有合并单元格的列表
// 导出async function exportExcel(fileName "共识调整.xlsx") {// 所有数据const exportData await getAllMainData();// 表头内容let fitstTitleList [];const secondTitleList [];allColumns.value.forEach(column > {if (!column.children) {fitstTitleL…...

CocosCreator 之 JavaScript/TypeScript和Java的相互交互
引擎版本: 3.8.1 语言: JavaScript/TypeScript、C、Java 环境:Window 参考:Java原生反射机制 您好,我是鹤九日! 回顾 在上篇文章中:CocosCreator Android项目接入UnityAds 广告SDK。 我们简单讲…...
在鸿蒙HarmonyOS 5中使用DevEco Studio实现录音机应用
1. 项目配置与权限设置 1.1 配置module.json5 {"module": {"requestPermissions": [{"name": "ohos.permission.MICROPHONE","reason": "录音需要麦克风权限"},{"name": "ohos.permission.WRITE…...

在WSL2的Ubuntu镜像中安装Docker
Docker官网链接: https://docs.docker.com/engine/install/ubuntu/ 1、运行以下命令卸载所有冲突的软件包: for pkg in docker.io docker-doc docker-compose docker-compose-v2 podman-docker containerd runc; do sudo apt-get remove $pkg; done2、设置Docker…...

Spring Cloud Gateway 中自定义验证码接口返回 404 的排查与解决
Spring Cloud Gateway 中自定义验证码接口返回 404 的排查与解决 问题背景 在一个基于 Spring Cloud Gateway WebFlux 构建的微服务项目中,新增了一个本地验证码接口 /code,使用函数式路由(RouterFunction)和 Hutool 的 Circle…...
08. C#入门系列【类的基本概念】:开启编程世界的奇妙冒险
C#入门系列【类的基本概念】:开启编程世界的奇妙冒险 嘿,各位编程小白探险家!欢迎来到 C# 的奇幻大陆!今天咱们要深入探索这片大陆上至关重要的 “建筑”—— 类!别害怕,跟着我,保准让你轻松搞…...
python爬虫——气象数据爬取
一、导入库与全局配置 python 运行 import json import datetime import time import requests from sqlalchemy import create_engine import csv import pandas as pd作用: 引入数据解析、网络请求、时间处理、数据库操作等所需库。requests:发送 …...
SpringAI实战:ChatModel智能对话全解
一、引言:Spring AI 与 Chat Model 的核心价值 🚀 在 Java 生态中集成大模型能力,Spring AI 提供了高效的解决方案 🤖。其中 Chat Model 作为核心交互组件,通过标准化接口简化了与大语言模型(LLM࿰…...
【WebSocket】SpringBoot项目中使用WebSocket
1. 导入坐标 如果springboot父工程没有加入websocket的起步依赖,添加它的坐标的时候需要带上版本号。 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId> </dep…...