数据库连接池的创建

首先我们需要知道,在执行构造方法之前会优先执行代码块

1.确保 Connect 接口的定义

首先,确保有一个 Connect 接口,并且这个接口扩展了 java.sql.Connection 接口。

java 复制代码
import java.sql.*;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.Executor;

public class Connect implements Connection{
//实现java.sql.Connection接口
}

2. 获取数据库连接

creatConnection 方法中通过 DriverManager 获取数据库连接,并将其存储在 connection 成员变量中。确保数据库 URL、用户名和密码是正确的。

3. 提供获取连接的方法

用getConnection 方法检查 connection 是否为 null,如果是,则调用 creatConnection 方法创建连接。

4. 管理连接的使用状态

你通过 isUse 变量来跟踪连接是否正在被使用。isUsed 方法用于检查并标记连接的使用状态。free 方法用于释放连接,将其标记为未使用。

MyConnection类

java 复制代码
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

// 继承自自定义的Connect接口,该接口实现了java.sql.Connection接口
public class MyConnection extends Connect {
    // 数据库连接信息
    String url = "jdbc:mysql:///test3?useSSL=false";
    String userName = "root";
    String password = "xxx";
    
    // 实际的数据库连接对象
    Connection connection = null;
    
    // 标记连接是否正在使用
    private boolean isUse = false;
    
    // 创建数据库连接
    public void creatConnection() {
        try {
            // 加载MySQL驱动
            Class.forName("com.mysql.jdbc.Driver");
            // 获取数据库连接
            connection = DriverManager.getConnection(url, userName, password);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    
    // 获取数据库连接
    public Connection getConnection() {
        // 如果连接未创建,则创建连接
        if (connection == null) {
            creatConnection();
        }
        return connection;
    }
    
    // 检查连接是否正在使用
    public boolean isUsed() {
        // 如果当前未使用,则标记为已使用,并返回false表示获取成功
        if (!isUse) {
            isUse = true;
            return false;
        } else {
            // 如果已在使用,则返回true表示获取失败
            return isUse;
        }
    }
    
    // 释放连接
    public boolean free() {
        // 标记为未使用
        isUse = false;
        return true;
    }
    
  
}

5. 静态实例

将构造方法设为私有(private),实现单例模式,防止外部类通过 new 关键字来创建 Pools 类的实例。定义一个静态的 Pools 类型变量 pools,并在类加载时通过静态代码块或直接在声明时初始化它。这样,无论何时调用 getInstance() 方法,都会返回同一个 Pools 实例。

6. 连接池

定义一个 List<MyConnection> 类型的变量 list 来存储连接池中的连接。这个列表将在类加载时被初始化,并填充一定数量的 MyConnection 对象。

7. 静态代码块初始化连接池

在静态代码块中,循环创建 5 个 MyConnection 对象,并将它们添加到 list 中。

8. 获取连接池实例的方法

你提供了 getInstance() 方法来返回连接池的静态实例。这个方法确保了整个应用中只有一个 Pools 实例被创建和访问。

9. 测试连接池大小

main 方法中,通过调用 getInstance() 方法获取了连接池的实例,并打印连接池的大小。这是一个简单的测试,用于验证连接池是否被正确初始化。

Pools

java 复制代码
import java.util.ArrayList;
import java.util.List;

// 单例模式的连接池管理类
public class Pools {
    // 私有构造方法,防止外部实例化
    private Pools() {}
    
    // 静态实例,实现单例模式
    private static Pools pools = new Pools();
    
    // 连接池,存储MyConnection对象
    List<MyConnection> list = new ArrayList<>();
    
    // 静态代码块,初始化连接池
    {
        // 在连接池中预先创建5个数据库连接
        for (int i = 0; i < 5; i++) {
            MyConnection myConnection = new MyConnection();
            list.add(myConnection);
        }
    }
    
    // 获取连接池实例
    public static Pools getInstance() {
        return pools;
    }
    
   
}

10. 获取连接池实例

首先,通过调用 Pools.getInstance() 方法获取了连接池的实例,并获取连接池中的连接列表。

11. 模拟数据库操作请求

使用一个 for 循环来模拟 10 次数据库操作请求。

12. 遍历连接池获取连接

在每次请求中,遍历连接池列表,查找一个未使用的连接(!conn.isUsed())。如果找到了,就跳出循环并使用这个连接。

13. 处理无可用连接的情况

如果没有找到可用的连接,模拟了等待一段时间(使用 Thread.sleep(10)

14. 执行数据库操作

使用获取到的连接,创建了一个 Statement 对象,并执行了一个简单的 SQL 插入操作。这里需要注意的是,应该确保 MyConnection 类的 getConnection() 方法返回的是一个有效的 java.sql.Connection 对象。

15. 释放连接

在操作完成后,调用了 myConnection.free() 方法来释放连接,以便其他请求可以使用它。

Test类

java 复制代码
package d117;

import java.sql.SQLException;
import java.sql.Statement;
import java.util.List;

// 测试类,模拟多个并发请求获取和释放数据库连接
public class Test {
    public static void main(String[] args) {
        // 获取连接池实例
        Pools pools = Pools.getInstance();
        List<MyConnection> list = pools.list;
        
        // 模拟10次数据库操作请求
        for (int i = 1; i <= 10; i++) {
            MyConnection myConnection = null;
            
            // 遍历连接池,获取一个可用的连接
            for (MyConnection conn : list) {
                if (!conn.isUsed()) {
                    myConnection = conn;
                    break;
                }
            }
            
            // 如果没有找到可用的连接,则等待一段时间重试(模拟等待连接释放)
            if (myConnection == null) {
                try {
                    Thread.sleep(10);
                    i--; // 重试当前请求
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                continue;
            }
            
            // 使用获取到的连接执行数据库操作
            try (Connection connection = myConnection.getConnection();
                 Statement statement = connection.createStatement()) {
                
                String sql = "INSERT INTO t1 VALUES (4, 4, 20)";
                int effectRows = statement.executeUpdate(sql);
                
                if (effectRows > 0) {
                    System.out.println("插入成功");
                } else {
                    System.out.println("插入失败");
                }
                
                // 释放连接
                myConnection.free();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
}
相关推荐
老猿讲编程16 分钟前
一个例子来说明Ada语言的实时性支持
开发语言·ada
Chrikk1 小时前
Go-性能调优实战案例
开发语言·后端·golang
幼儿园老大*1 小时前
Go的环境搭建以及GoLand安装教程
开发语言·经验分享·后端·golang·go
canyuemanyue1 小时前
go语言连续监控事件并回调处理
开发语言·后端·golang
杜杜的man1 小时前
【go从零单排】go语言中的指针
开发语言·后端·golang
测开小菜鸟1 小时前
使用python向钉钉群聊发送消息
java·python·钉钉
Ai 编码助手2 小时前
MySQL中distinct与group by之间的性能进行比较
数据库·mysql
P.H. Infinity2 小时前
【RabbitMQ】04-发送者可靠性
java·rabbitmq·java-rabbitmq
生命几十年3万天2 小时前
java的threadlocal为何内存泄漏
java
陈燚_重生之又为程序员3 小时前
基于梧桐数据库的实时数据分析解决方案
数据库·数据挖掘·数据分析