代码实现数据库连接池

【归纳总结】数据库之连接池 我们用 JDBC 操作数据库的时候,每次操作完都会将连接关闭。数据库连接是极其宝贵的资源,频繁的创建和销毁会极大地降低服务器的性能。因此,我们可以利用池化技术,重复利用数据库资源,避免没必要的开销。 用口语来说,相当于我们创建了一个池子,这个池子里面放的都是一些JDBC的连接,也就是Connection对象,每当我们需要时,我们去从连接池里面获取连接,使用完了连接,放回连接池,做到连接的反复使用。 手写一个数据库连接池 思路: 要实现DataSource接口(SUN公司就制定的连接池的标准) 要有一个ge 阅读详情

数据库连接池

1. 数据库连接池原理

在内部对象池中,维护一定数量的数据库连接,并对外暴露数据库连接的获取和返回方法。

如外部使用者可通过getConnection方法获取数据库连接,使用完毕后再通过releaseConnection方法将连接返回,注意此时的连接并没有关闭,而是由连接池管理器回收,并为下一次使用做好准备。

2. 连接池作用

  1. 资源重用
    由于数据库连接得到重用,避免了频繁创建、释放连接引起的大量性能开销。在减少系统消耗的基础上,增进了系统环境的平稳性(减少内存碎片以级数据库临时进程、线程的数量)
  2. 更快的系统响应速度
    数据库连接池在初始化过程中,往往已经创建了若干数据库连接置于池内备用。此时连接池的初始化操作均已完成。对于业务请求处理而言,直接利用现有可用连接,避免了数据库连接初始化和释放过程的时间开销,从而缩减了系统整体响应时间。
  3. 新的资源分配手段
    对于多应用共享同一数据库的系统而言,可在应用层通过数据库连接的配置,实现数据库连接技术。
  4. 统一的连接管理,避免数据库连接泄露
    在较为完备的数据库连接池实现中,可根据预先的连接占用超时设定,强制收回被占用的连接,从而避免了常规数据库连接操作中可能出现的资源泄露

纯手写数据库连接池

开始之前可以回顾下jdbc的内容

倚赖仅导入驱动即可

<dependency>
  <groupId>mysql</groupId>
  <artifactId>mysql-connector-java</artifactId>
  <version>5.1.38</version>
</dependency>
  1. 读取外部配置信息
//外部配置文件信息
public class DbBean {

	/* 链接属性 */
	private String driverName = "com.mysql.jdbc.Driver";

	private String url = "jdbc:mysql://localhost:3306/test";

	private String userName = "root";

	private String password = "root";

	private String poolName = "thread01";// 连接池名字

	private int minConnections = 1; // 空闲池,最小连接数

	private int maxConnections = 10; // 空闲池,最大连接数

	private int initConnections = 5;// 初始化连接数

	private long connTimeOut = 1000;// 重复获得连接的频率

	private int maxActiveConnections = 100;// 最大允许的连接数,和数据库对应 

	private long connectionTimeOut = 1000 * 60 * 20;// 连接超时时间,默认20分钟

	//getter setter
}

其中较为关键的参数为空闲池数量,当有线程获取连接时,会首先判断创建的连接数是否小于maxActiveConnections ,大于线程将进行等待,小于将会从空闲池中进行取,如果能取到,则会放入活动池中,如果取不到,则新建连接,然后再放入活动池中。
释放连接时会首先判断 空闲连接池是否已满,如果已满则直接释放,如果未满则会将连接从活动池转入空闲池中

  1. 创建接口
//连接数据库池
public interface IConnectionPool {

	// 获取连接(重复利用机制)
	public Connection getConnection();

	// 释放连接(可回收机制)
	public void releaseConnection(Connection connection);
}

  1. 创建数据库连接池

/**
 * ####核心参数######
 * 1.空闲线程 容器 没有被使用的连接存放
 * 2.活动线程 容器正在使用的连接
 * ###核心步骤#####
 * 1. 初始化线程池(初始化空闲线程)
 * 2. 调用getConnection方法 --- 获取连接
 * ## 2.1先去freeConnection获取当前连接,存放在activeConnection
 * 3.调用releaseConnection方法 ----释放连接----资源回收
 * ## 3.1获取activeConnection集合连接,转移到 freeConnection集合中
 */
public class ConnectionPool implements IConnectionPool {
	// 使用线程安全的集合 空闲线程 容器 没有被使用的连接存放
	private List<Connection> freeConnection = new Vector<Connection>();
	// 使用线程安全的集合 活动线程 容器 容器正在使用的连接
	private List<Connection> activeConnection = new Vector<Connection>();
	private DbBean dbBean;
	private static AtomicInteger countConne = new AtomicInteger();


	public ConnectionPool(DbBean dbBean) {
		// 获取配置文件信息
		this.dbBean = dbBean;
		init();
	}

	// 初始化线程池(初始化空闲线程)
	private void init(){
		if (dbBean == null) {
			try {
				throw new Exception("配置文件初始化失败");
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		// 1.获取初始化连接数
		for (int i = 0; i < dbBean.getInitConnections(); i++) {
			// 2.创建Connection连接
			Connection newConnection = newConnection();
			if (newConnection != null) {
				// 3.存放在freeConnection集合
				freeConnection.add(newConnection);
			}
		}

	}

	// 创建Connection连接
	private  Connection newConnection() {
		try {
			Class.forName(dbBean.getDriverName());
			Connection connection = DriverManager.getConnection(dbBean.getUrl(), dbBean.getUserName(),
					dbBean.getPassword());
			countConne.incrementAndGet();
			return connection;
		} catch (Exception e) {
			return null;
		}

	}

	// 调用getConnection方法 --- 获取连接
	public  Connection getConnection() {

		try {
			Connection connection = null;
			if (countConne.get() < dbBean.getMaxActiveConnections()) {
				// 小于最大活动连接数
				// 1.判断空闲线程是否有数据
				if (freeConnection.size() > 0) {
					// 空闲线程有存在连接
					// ==freeConnection.get(0);freeConnection.remove(0)
					// 拿到在删除
					connection = freeConnection.remove(0);
				} else {
					// 创建新的连接
					connection = newConnection();
				}
				// 判断连接是否可用
				boolean available = isAvailable(connection);
				if (available) {
					// 存放在活动线程池
					activeConnection.add(connection);
				} else {
					countConne.decrementAndGet();
					connection = getConnection();// 怎么使用重试? 递归算法
				}

			} else {
				// 大于最大活动连接数,进行等待
				wait(dbBean.getConnTimeOut());
				// 重试
				connection = getConnection();
			}
			return connection;
		} catch (Exception e) {
			return null;
		}

	}

	// 判断连接是否可用
	public boolean isAvailable(Connection connection) {
		try {
			if (connection == null || connection.isClosed()) {
				return false;
			}
		} catch (Exception e) {

			// TODO: handle exception
		}
		return true;

	}

	// 释放连接 回收
	public void releaseConnection(Connection connection) {
		try {
			// 1.判断连接是否可用
			if (isAvailable(connection)) {
				// 2.判断空闲线程是否已满
				if (freeConnection.size() < dbBean.getMaxConnections()) {
					// 空闲线程没有满
					freeConnection.add(connection);// 回收连接
				} else {
					// 空闲线程已经满
					connection.close();
				}
				activeConnection.remove(connection);
				countConne.decrementAndGet();
				notifyAll();
			}
		} catch (Exception e) {
			// TODO: handle exception
		}

	}

}

创建管理类:


// 管理线程池
public class ConnectionPoolManager {
	private static DbBean dbBean = new DbBean();
	private static ConnectionPool connectionPool = new ConnectionPool(dbBean);

	// 获取连接(重复利用机制)
	public static Connection getConnection() {
		return connectionPool.getConnection();
	}

	// 释放连接(可回收机制)
	public static void releaseConnection(Connection connection) {
		connectionPool.releaseConnection(connection);
	}
}

测试运行结果


public class Test01 {

	public static void main(String[] args) {
		ThreadConnection threadConnection = new ThreadConnection();
		for (int i = 0; i < 2; i++) {
			Thread thread = new Thread(threadConnection, "线程i:" + i);
			thread.start();
		}
	}

}

class ThreadConnection implements Runnable {

	public void run() {
		for (int i = 0; i < 101; i++) {
			Connection connection = ConnectionPoolManager.getConnection();
			System.out.println(Thread.currentThread().getName() + ",connection-"+i+":" + connection);
			ConnectionPoolManager.releaseConnection(connection);
		}
	}

}

资源池模式和单例模式实现的自定义数据库连接池java实现版 在企业级开发中,我们往往不会直接使用原生的JDBC操作来实现与数据库得连接。因为数据库的连接是一个很宝贵的资源且耗时,我们往往会在内存中引入一个资源池来统一管理数据库的连接。这个模式也被总结为一种设计模式:资源池模式和单例模式。关于原理部分就不多做介绍了,这里也是做一个简单的原理实现。 ObjectPool连接池接口 package com.test.pool; import java.util... 阅读详情

相关推荐

数据库连接池java代码实现

用java代码详细描述了连接池的原理实现,注释也非常详细

创建数据库连接池

1.流程 创建linkedlist集合用来充当容器存储连接 读取properties配置文件, 注册驱动 初始化连接 连接数据库 将链接放入集合中 package com.gxa; import javax.sql.DataSource; import java.io.IOException; import java.io.InputStream; import java.io.PrintWriter; import java.lang.reflect.InvocationHandler;

ZhuRuiccc的博客 838

Java建立数据库连接池

对于一个简单的数据库引用,用于对数据库的访问不是很频繁。这时可以简单的在需要访问数据库是,创建一个连接,用完后关闭它,这样做也不会带来什么明显的性能上的开销。但是对于一个复杂的数据库引用,情况完全不同了。频繁的建立、关闭连接,会极大的减低系统的性能,因为对于连接的使用成了系统性能的瓶颈。   对于共享资源,有一个很的设计模式:资源池。该模式正是为了解决资源频繁分配、释放所造成的问题的。把该模式应用到数据库连接管理领域,是建立一个数据库连接池,提供一套高效的连接分配、使用策略,终目标是实现连接的高效、安全的复用。   数据库连接池的基本原理是在内部对象池中维护一定数量的数据库连接,并对外暴露

实现高效的数据库连接池(附带完整代码C#和Java实现)

相关技术: 连接池 引用记数 多线程 C#.Net Java 目录 引言 数据库连接池(Connection Pool)的工作原理 连接池关键问题分析 并发问题 事务处理 连接池的分配与释放 连接池的配置与维护 关键议题 引用记数 如何实现事务处理  管理连接池 结合代码说明 构造方法 启动服务

哈库纳 1万+

NXP S32K5 MCU如何赋能Zonal架构与软件定义汽车?

汽车电子架构正从分布式ECU向域集中、再向Zonal分区架构演进,核心驱动力在于线束简化、算力下沉与软件分层解耦。区域控制器作为物理区域的“调度员”,需要同时满足实时响应、功能安全、多网络协议转换和OTA升级等要求,这使MCU与SoC的选型成为系统工程的关键决策。MCU凭借确定性的微秒级启动、低功耗、丰富的IO控制以及成熟的ASIL-D认证路径,仍是区域控制器的主流选择。NXP S32K5正是面向这一场景发布的系列MCU:它集成多核锁步、CAN-XL、TSN以太网、硬件安全模块与双Bank Flash,补齐

weixin_28721917的博客 356

HFSS 3D LAOUT PCB 裁剪,差分线,过孔仿真和优化

我本身不是做天线设计的,所以HFSS这个软件给我主要还是做PCB级别的高速信号完整性仿真,一般2.5D的仿真软件无法对过孔和跨平面进行仿真。所以要借助三维电磁软件进行。今天就针对PCB进行裁剪。为什么要裁剪?以为如果把整个PCB一起仿真的话,应该要好几个月吧。所以为了加快仿真速度,必须进行裁剪仿真。①candence的PCB可以直接导入。那么先导入brd文件,file-import-candence结果如下②点击cutout,选中要仿真的net和参考平面。这里最好选creat new不然会把原文件覆盖掉。注

gjatwfn的专栏 1万+

java数据库连接池代码实现

连接池原理已经解释了,下面该看看代码是如何实现的吧     数据库连接池有很多,我就不一一列举了,有 dbcp,c3p0, Proxool,BoneCP,Druid............强迫症可以自己去百度,然后背下来 简单介绍一下, DBCP(DataBase connection pool),数据库连接池。是 apache 上的一个 java 连接池项目,也是 tomcat 使

qq_14926283的博客 2107

速腾RS-LiDAR-16激光雷达ROS配置全攻略:从硬件连接到Rviz点云可视化

本文详细介绍了速腾RS-LiDAR-16激光雷达在ROS环境中的配置与使用全攻略,涵盖硬件连接、网络配置、ROS驱动安装及Rviz点云可视化等关键步骤。通过实战案例和技术解析,帮助开发者快速实现激光雷达数据采集与处理,提升机器人感知系统的部署效率。

ooo22的博客 248

VC下的ADO连接池

由于工作需要,查找了很多关于数据库连接池的实现代码.但是发现很多都是JAVA  版本的.我试着改了一下,代码如下:/********************************************************************  ADO 对象的简单封装*************************************************************

xiaoly_caep的专栏 4997

深圳SILAS(智能融合低空系统)无人机调度系统介绍

一、系统定位与核心目标SILAS(Smart Integrated Lower Airspace System)是深圳市为低空经济打造的“数字大脑”,由粤港澳大湾区数字经济研究院自主研发,定位为城市级低空飞行智能调度与管理平台。核心目标是解决低空经济中“高密度、高复杂度、多主体”的飞行调度难题,实现空域资源的高效分配、飞行安全的智能监管及全场景服务的无缝协同,支撑深圳从“无人机之都”向“天空之城”升级。二、核心架构:低空基础设施“四张网”设施网。

主攻大数据 人工智能 物联网 安全 低空经济等方向。mtsc 、gtest特邀分享嘉宾 3742

手把手教你学simulink(95.1)--PID控制实例:基于Simulink的PID控制温度控制系统建模与仿真

温度控制是工业自动化、家用电器、医疗设备以及航空航天等领域中常见的控制问题。通过精确的温度控制,可以提高生产效率、降低能耗并确保产品质量。PID(比例-积分-微分)控制器因其结构简单、性能稳定且易于实现而被广泛应用于各种温度控制系统。本项目旨在通过MATLAB/Simulink平台设计和验证一个基于PID控制的温度控制系统,重点研究PID参数调优方法、系统动态响应特性以及稳态误差消除能力。

MHD0815的博客 792

数据库连接池代码实现

数据库连接池代码实现 步骤 大体步骤和之前封装JDBC差不多,不懂的可以去看看上一篇blog。 所以今天我简单描述一下。 在src目录创建一个配置文件db.properties DRIVER:com.mysql.jdbc.Driver URL:jdbc:mysql://localhost:3306/db214 USER:root PASSWORD:123456 ...

呼卓宇的博客 1067

C# 上位机 YOLO 实战:从数据采集到目标识别的全流程拆解

本文以工业螺栓缺陷检测为例,完整拆解了C#上位机+YOLO从数据采集到目标识别的全流程。数据采集:保证图像质量,线程安全采集,必要时归档数据;预处理:适配YOLO模型输入格式,复用对象减少内存开销;推理解析:正确解析张量结果,过滤低置信度目标;落地环节:可视化展示结果,实现工业交互和日志记录。

这里只有干货:从 Modbus 通信到 MES 对接,从 YOLO 训练到工控机部署,带你搞定工业软件开发全流程。 1452

几行代码实现完美 QT数据库连接池 低耦合

【代码】几行代码实现完美 QT数据库连接池 低耦合。

qq_32854345的博客 531

【HALCON 25.11 + C#】 01:2026年工业机器视觉实战详解(从入门到精通)

2026年机器视觉市场规模将突破230亿美元,HALCON 25.11的革命性更新与C#的工业集成优势形成黄金技术栈。本文作为付费专栏开篇序章,聚焦“为什么现在必须学25.11+C#”的核心问题,通过真实工业案例、五项核心技术突破、联合编程架构优势及30篇系统学习路线,全方位论证其投资价值。读者将掌握持续学习、深度OCR加速等关键技能,获得可直接上产线的工业级代码资产与架构设计思维,解决柔性生产、边缘部署等核心痛点,成为具备技术溢价的机器视觉工程师。

专注于人工智能、软件开发、工控自动化、工厂数字化及智能化等领域,希望和大家共同进步! 1218

【C++】构造函数之初始化列表(Initialization list of constructors)

本讲主要是构造函数的初始化列表的讲节,但是本节很重要,可以关乎后面写项目

m0_62599305的博客 2232

Java实现数据库连接池的代码

<br />package com.kyo.connection;    import java.sql.Connection;  import java.sql.DatabaseMetaData;  import java.sql.Driver;  import java.sql.DriverManager;  import java.sql.SQLException;  import java.sql.Statement;  import java.util.Enumeration;  import j

GetStudyMessages的专栏 6624

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

自定义数据库连接池实现代码

一、数据库连接池的简单搭建 备注:其他方法未实现,不在代码中展现 package com.util; import java.io.PrintWriter; import java.sql.Connection; import java.sql.SQLException; import java.sql.SQLFeatureNotSupportedException; import java.u...

weixin_44270855的博客 467

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

java数据库连接池原理,代码实现

数据库连接池根据原理简单实现代码,看看代码就懂了

qq_14926283的博客 472

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

mysql数据池代码_Python实现Mysql数据库连接池

python连接Mysql数据库:python编程中可以使用MySQLdb进行数据库的连接及诸如查询/插入/更新等操作,但是每次连接mysql数据库请求时,都是独立的去请求访问,相当浪费资源,而且访问数量达到一定数量时,对mysql的性能会产生较大的影响。因此,实际使用中,通常会使用数据库的连接池技术,来访问数据库达到资源复用的目的。python的数据库连接池包 DBUtils:DBUtils是一...

weixin_30914893的博客 235

JDBC 数据库连接池 实现代码一(介绍)

文章转自:http://hi.baidu.com/cpmroom/blog/item/4e9a8490cf23628aa977a4a0.html 虽然 J2EE 程序员一般都有现成的应用服务器所带的JDBC 数据库连接池,不过对于开发一般的 Java Application 、 Applet 或者 JSP、velocity 时,我们可用的JDBC 数据库连接池并不多,并且一般性...

sakyoneone的专栏 411

数据库连接池详解与代码实现

一、数据库连接池概念        数据库连接池:负责分配、管理和释放数据库连接,它允许应用程序重复使用一个现有的数据库连接,而不是再重新建立一个;释放空闲时间超过最大空闲时间的数据库连接来避免因为没有释放数据库连接而引起的数据库连接遗漏。这项技术能明显提高对数据库操作的性能。 二、背景        数据库连接是一种关键的有限的昂贵的资源,这一点在多用户的网页应用程序中体现得尤为突出。对数...

春风化雨 3210

如何编写出高效的数据库连接池(附带完整代码C#和Java实现) (转)

如何编写出高效的数据库连接池(附带完整代码C#和Java实现)  相关技术: 连接池 引用记数 多线程 Timer类运行基理 C#.Net Java 适宜人群 数据库应用程序程序员 系统分析员 模块设计师 有一定功底的程序员 目

Welcome to Eric Zhang's blog 1039
上一篇: 代码实现SpringMVC基本功能
下一篇: 代码实现Mybatis注解版本框架
金心靖晨
博客等级 码龄9年 460粉丝 211原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值