当前位置:网站首页>数据库连接池的简单实现
数据库连接池的简单实现
2022-07-01 05:23:00 【lanleihhh】
配置文件
driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://127.0.0.1:3306/ssm?characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai
uname=root
pwd=lanlei6843
将配置文件database.properties放在src目录下,将src的Project Structure 修改为Resource; 就可以通过properties.load加载进来了
连接池的参数
package com.ffyc.writepool.connectionpool;
import java.io.IOException;
import java.util.Properties;
/** * 连接池中的一些参数 */
public class ConnectionPoolParam {
private String driver;//数据库驱动
private String url;//要连接的数据库的url
private String user;//DB用户名
private String password;//DB密码
private int minConnectionNum;//最小连接数
private int maxConnectionNum;//最大连接数
private long maxFreeTime;//连接最大空闲时间
private long maxWaitTime;//获取连接的最大等待时间
private int autoIncrementConnNum = 5;//自动增加连接的数量
public ConnectionPoolParam() {
Properties properties = new Properties();
try {
properties.load(this.getClass().getClassLoader().getResourceAsStream("database.properties"));
} catch (IOException e) {
throw new RuntimeException(e);
}
this.driver = properties.getProperty("driver");
this.url = properties.getProperty("url");
this.user = properties.getProperty("uname");
this.password = properties.getProperty("pwd");
}
public String getDriver() {
return driver;
}
public void setDriver(String driver) {
this.driver = driver;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getUser() {
return user;
}
public void setUser(String user) {
this.user = user;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public int getMinConnectionNum() {
return minConnectionNum;
}
public void setMinConnectionNum(int minConnectionNum) {
this.minConnectionNum = minConnectionNum;
}
public int getMaxConnectionNum() {
return maxConnectionNum;
}
public void setMaxConnectionNum(int maxConnectionNum) {
this.maxConnectionNum = maxConnectionNum;
}
public long getMaxFreeTime() {
return maxFreeTime;
}
public void setMaxFreeTime(long maxFreeTime) {
this.maxFreeTime = maxFreeTime;
}
public long getMaxWaitTime() {
return maxWaitTime;
}
public void setMaxWaitTime(long maxWaitTime) {
this.maxWaitTime = maxWaitTime;
}
public int getAutoIncrementConnNum() {
return autoIncrementConnNum;
}
public void setAutoIncrementConnNum(int autoIncrementConnNum) {
this.autoIncrementConnNum = autoIncrementConnNum;
}
@Override
public String toString() {
return "ConnectionPoolParam{" +
"driver='" + driver + '\'' +
", url='" + url + '\'' +
", user='" + user + '\'' +
", password='" + password + '\'' +
", minConnectionNum=" + minConnectionNum +
", maxConnectionNum=" + maxConnectionNum +
", maxFreeTime=" + maxFreeTime +
", maxWaitTime=" + maxWaitTime +
'}';
}
}
连接池中的连接对象
package com.ffyc.writepool.connectionpool;
import java.sql.Connection;
/** * 池化的连接 * 数据库连接池中的连接 * 包含 连接 与 使用状态 两个属性 */
public class PooledConnection {
//数据库连接
private Connection connection;
//是否被使用
private boolean isUsed;
//构造一个池化连接对象
public PooledConnection(Connection connection) {
this.connection = connection;
}
public Connection getConnection() {
return connection;
}
public void setConnection(Connection connection) {
this.connection = connection;
}
public boolean isUsed() {
return isUsed;
}
public void setUsed(boolean used) {
isUsed = used;
}
}
连接池
package com.ffyc.writepool.connectionpool;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Iterator;
import java.util.concurrent.CopyOnWriteArrayList;
public class ConnectionPool {
private ConnectionPoolParam param;//连接池中的参数
private CopyOnWriteArrayList<PooledConnection> connections;//连接池中存放连接的集合
/** * 构造一个指定参数的连接池 * @param param 连接池参数对象 */
public ConnectionPool(ConnectionPoolParam param) {
this.param = param;
}
//获取连接池参数
public ConnectionPoolParam getParam() {
return param;
}
//设置连接池参数
public void setParam(ConnectionPoolParam param) {
this.param = param;
}
//创建数据库连接池
public synchronized void createPool() throws ClassNotFoundException, SQLException {
//如果已经创建过,就不创建了
if(connections != null){
return;
}
System.out.println("param:" + param);
//加载驱动
Class.forName(this.getParam().getDriver());
//创建一个集合用来保存连接池中的连接
connections = new CopyOnWriteArrayList<>();
//创建指定数量的连接
createConnection(this.getParam().getMinConnectionNum());
System.out.println("连接池创建成功!");
}
/** * 创建 minConnectionNum 连接,将这些连接放入连接池(集合) connections中 * @param minConnectionNum 最小连接数 */
private void createConnection(int minConnectionNum) {
for (int i = 0; i < minConnectionNum; i++) {
//当前连接数 达到 最大连接数 就退出创建
if(this.param.getMaxConnectionNum() > 0 && this.connections.size() >= this.param.getMaxConnectionNum()){
break;
}
//添加一个新的 池化连接 到连接池中
try {
connections.add(new PooledConnection(newConnection()));
} catch (SQLException e) {
System.out.println(" 创建数据库连接失败! " + e.getMessage());
throw new RuntimeException(e);
}
System.out.println("数据库连接Connection 已创建!");
}
}
/** * 创建新的连接,并返回 * @return 新创建的数据库连接 */
private Connection newConnection() throws SQLException {
//创建一个新的数据库连接
Connection connection = DriverManager.getConnection(this.param.getUrl(), this.param.getUser(), this.param.getPassword());
//
if(connections.size() == 0){
DatabaseMetaData metaData = connection.getMetaData();
int dbMaxConnections = metaData.getMaxConnections();
//dbMaxConnections=0 表示数据库没有最大连接限制 或 获取不到最大连接限制
//如果数据库有最大连接限制
if(dbMaxConnections > 0){
//若连接池中最大连接数 > 数据库允许的最大连接数
if(this.param.getMaxConnectionNum() > dbMaxConnections){
//将连接池最大连接数 置为 数据库允许的最大连接数
this.param.setMaxConnectionNum(dbMaxConnections);
}
}
}
return connection;
}
/** * 返回一个空闲的数据库连接 * 如果没有空闲的连接,且不能再新建连接 就同步等待 * @return 返回一个空闲的连接 */
public synchronized Connection getConnection() throws SQLException, InterruptedException {
System.out.print("正在获取连接-->");
//如果连接池还没有被创建,无法获取连接
if(connections == null){
return null;
}
//获取一个空闲连接
Connection connection = getFreeConnection();
while (connection == null){
Thread.sleep(1000);
//再次尝试,直到获取到空闲连接
connection = getFreeConnection();
}
return connection;
}
/** * 从池中获取一个空闲的连接, * 若池中所有连接都被使用,返回null * @return 返回空闲的连接 */
private Connection getFreeConnection() throws SQLException {
System.out.print("正在获取空闲连接-->");
//获取到一个空闲的连接
Connection connection = findFreeConnection();
//如果连接池中没有空闲连接
if(connection == null){
//创建一些连接(一次5个,如果已经达到最大连接数,就不再创建)
createConnection(this.param.getAutoIncrementConnNum());
//创建后,再次查询有无空闲连接
connection = findFreeConnection();
//仍无空闲连接,返回null
if(connection == null){
return null;
}
}
return connection;//返回获取到的空闲连接
}
/** * 在池中查找空闲的连接,找不到返回null * @return 返回空闲的连接 */
private Connection findFreeConnection() {
System.out.println("正在寻找空闲连接...");
Connection connection = null;
PooledConnection pooledConnection = null;
//获取集合里的所有 池化连接
Iterator<PooledConnection> iterator = connections.iterator();
while (iterator.hasNext()){
pooledConnection = iterator.next();
//如果该池化连接没有被使用
if(!pooledConnection.isUsed()){
//拿到该连接
connection = pooledConnection.getConnection();
//设置该连接状态为已使用
pooledConnection.setUsed(true);
//找到了空闲的连接,退出
break;
}
}
return connection;
}
/** * 返回给连接池一个连接对象,置为空闲状态 * * @param conn 要返回的连接对象 */
public void returnConnection(Connection connection){
//连接池不存在,不能返回
if(connections == null){
throw new IllegalArgumentException("连接池还未创建,无法将连接归还到连接池!");
}
PooledConnection pooledConnection = null;
Iterator<PooledConnection> iterator = connections.iterator();
//遍历连接池中所有连接,找到这个要返回的连接
while (iterator.hasNext()){
pooledConnection = iterator.next();
if(connection == pooledConnection.getConnection()){
//找到该连接,将状态置为空闲
pooledConnection.setUsed(false);
break;
}
}
}
/** * 刷新连接池中的连接对象 */
public synchronized void refreshConnection() throws InterruptedException, SQLException {
if(connections == null){
throw new IllegalArgumentException("连接池未创建,无法刷新!");
}
PooledConnection pooledConnection = null;
Iterator<PooledConnection> iterator = connections.iterator();
while (iterator.hasNext()){
//拿到池中对象
pooledConnection = iterator.next();
//如果连接正在被使用,等待10s再刷新
if(pooledConnection.isUsed()){
Thread.sleep(10000);
}
//1.关闭该连接
closeConnection(pooledConnection.getConnection());
//2.使用新连接代替
pooledConnection.setConnection(newConnection());
//3.设置新连接状态为 空闲
pooledConnection.setUsed(false);
}
}
/** * 关闭一个指定的连接 * @param connection */
private void closeConnection(Connection connection) {
try {
connection.close();
} catch (SQLException e) {
throw new IllegalArgumentException(" 关闭数据库连接出错: " + e.getMessage());
}
}
/** * 关闭连接,清空连接池 */
public synchronized void closeConnectionPool() throws InterruptedException {
if(connections == null){
throw new IllegalArgumentException("连接池不存在,无法关闭!");
}
PooledConnection pooledConnection = null;
Iterator<PooledConnection> iterator = connections.iterator();
while (iterator.hasNext()){
pooledConnection = iterator.next();
//如果当前连接正在使用,等待10s后直接关闭
if(pooledConnection.isUsed()){
Thread.sleep(10000);
}
//关闭当前连接
closeConnection(pooledConnection.getConnection());
//从池中删除当前连接
connections.remove(pooledConnection);
}
//清空连接池
connections = null;
}
}
测试
package com.ffyc.writepool.test;
import com.ffyc.writepool.connectionpool.ConnectionPool;
import com.ffyc.writepool.connectionpool.ConnectionPoolParam;
import java.sql.Connection;
import java.sql.SQLException;
public class TestConnectionPool {
public static void main(String[] args) throws Exception {
ConnectionPoolParam param = new ConnectionPoolParam();
param.setMaxConnectionNum(20);//最大连接数
param.setMinConnectionNum(5);//最小连接数
param.setAutoIncrementConnNum(5);//每次新增连接的数量
param.setMaxFreeTime(60);//最大空闲时间60s
param.setMaxWaitTime(5);//最长等待时间
//1.构造数据库连接池
ConnectionPool pool = new ConnectionPool(param);
//2.获取数据库连接
Connection connection = pool.getConnection();
//3.创建连接池
pool.createPool();
//获取连接
Connection[] connections = new Connection[21];
for (int i = 0; i < connections.length; i++) {
connections[i] = pool.getConnection();
System.out.println(i+1+":"+connections[i]);
}
}
}
先创建了最小连接数的连接对象(5个)


边栏推荐
- Manually implement a simple stack
- LevelDB源码分析之memtable
- Global and Chinese market of solder wire 2022-2028: Research Report on technology, participants, trends, market size and share
- And search: the suspects (find the number of people related to the nth person)
- Web Security (IX) what is JWT?
- Use of STM32 expansion board temperature sensor and temperature humidity sensor
- Tcp/ip explanation (version 2) notes / 3 link layer / 3.2 Ethernet and IEEE 802 lan/man standards
- AcWing 885. Find the combination number I (recursive preprocessing)
- Understand several related problems in JVM - JVM memory layout, class loading mechanism, garbage collection
- Design and application of immutable classes
猜你喜欢

How to create a progress bar that changes color according to progress

Go learning notes (5) basic types and declarations (4)

Cockroachdb: the resistant geo distributed SQL database paper reading notes

了解 JVM 中几个相关问题 — JVM 内存布局、类加载机制、垃圾回收

Distributed transactions - Solutions

Set集合詳細講解

STM32 expansion board digital tube display

Single page application

eBPF Cilium实战(2) - 底层网络可观测性

Ebpf cilium practice (2) - underlying network observability
随机推荐
Global and Chinese market of protection circuit modules 2022-2028: Research Report on technology, participants, trends, market size and share
And search: the suspects (find the number of people related to the nth person)
How to meet the requirements of source code confidentiality and source code security management
第05天-文件操作函数
3D建模與處理軟件簡介 劉利剛 中國科技大學
AcWing 884. Gauss elimination for solving XOR linear equations
AcWing 889. 01 sequence satisfying the condition (Cartland number)
Numeric amount plus comma; JS two methods of adding three digits and a comma to numbers; JS data formatting
Rainbond结合NeuVector实践容器安全管理
How to hide browser network IP address and modify IP internet access?
Actual combat: basic use of Redux
工业导电滑环的应用
Set set detailed explanation
CockroachDB: The Resilient Geo-Distributed SQL Database 论文阅读笔记
[data recovery in North Asia] a data recovery case of raid crash caused by hard disk drop during data synchronization of hot spare disk of RAID5 disk array
Sqlplus connects using the instance name
Cockroachdb: the resistant geo distributed SQL database paper reading notes
Introduction to 3D modeling and processing software Liu Ligang University of science and technology of China
如何选择导电滑环材料
Global and Chinese markets for soft ferrite cores 2022-2028: Research Report on technology, participants, trends, market size and share