Java c3p0 连接池参数测试与连接不足异常处理

Java 使用 C3P0 数据库连接池,并测试 minPoolSizemaxPoolSize 的设置。并测试超出连接池的最大连接数的情况。

依赖配置

<dependencies>
    <dependency>
        <groupId>com.mchange</groupId>
        <artifactId>c3p0</artifactId>
        <version>0.9.5.5</version>
    </dependency>
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>8.0.33</version>
    </dependency>
</dependencies>

Java实现代码

import com.mchange.v2.c3p0.ComboPooledDataSource;
import com.mchange.v2.c3p0.management.C3P0Registry;
import com.mchange.v2.c3p0.management.ActiveManagementCoordinator;

import java.beans.PropertyVetoException;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

public class C3P0ConnectionTest {

    // 创建 C3P0 数据源实例
    private static final ComboPooledDataSource dataSource = new ComboPooledDataSource();

    public static void main(String[] args) throws PropertyVetoException, InterruptedException {
        // 配置 C3P0 数据源参数
        configureDataSource();

        // 开启线程实时打印连接池状态
        startConnectionPoolMonitoring();

        // 模拟连接数不足的测试场景
        simulateConnectionUsage();
    }

    // 配置 C3P0 数据源的参数
    private static void configureDataSource() throws PropertyVetoException {
        dataSource.setDriverClass("com.mysql.cj.jdbc.Driver"); // MySQL 驱动
        dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/test_db"); // 数据库 URL
        dataSource.setUser("root"); // 数据库用户名
        dataSource.setPassword("password"); // 数据库密码

        // 配置 C3P0 的核心参数
        dataSource.setInitialPoolSize(5);    // 初始连接数
        dataSource.setMinPoolSize(5);        // 最小连接数
        dataSource.setMaxPoolSize(10);       // 最大连接数
        dataSource.setMaxIdleTime(300);      // 空闲连接的最大存活时间(秒)
        dataSource.setAcquireIncrement(2);   // 当连接池耗尽时,每次尝试增长的连接数
        dataSource.setMaxStatements(50);     // 最大缓存的 SQL 语句数量
        dataSource.setCheckoutTimeout(2000); // 获取连接的超时时间(毫秒)
        dataSource.setTestConnectionOnCheckout(true); // 获取连接时检测其有效性
    }

    // 模拟使用连接的场景,测试连接数不足的报错
    private static void simulateConnectionUsage() {
        List<Connection> connections = new ArrayList<>();
        try {
            System.out.println("开始模拟数据库连接使用...");
            for (int i = 1; i <= 15; i++) { // 尝试超出最大连接数
                System.out.println("尝试获取第 " + i + " 个连接...");
                Connection connection = dataSource.getConnection();
                connections.add(connection); // 保存连接以防止被释放
                System.out.println("成功获取第 " + i + " 个连接");
                Thread.sleep(2000); // 模拟连接占用时间
            }
        } catch (SQLException e) {
            System.err.println("连接数不足,无法获取更多连接!");
            e.printStackTrace();
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        } finally {
            // 释放所有连接
            for (Connection conn : connections) {
                try {
                    if (conn != null && !conn.isClosed()) {
                        conn.close();
                        System.out.println("连接已释放");
                    }
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    // 开启线程,实时监控连接池状态
    private static void startConnectionPoolMonitoring() {
        new Thread(() -> {
            while (true) {
                try {
                    // 获取连接池的运行时状态
                    int totalConnections = dataSource.getNumConnectionsDefaultUser();
                    int busyConnections = dataSource.getNumBusyConnectionsDefaultUser();
                    int idleConnections = dataSource.getNumIdleConnectionsDefaultUser();

                    // 打印连接池的实时状态
                    System.out.println("\n[连接池状态]");
                    System.out.println("总连接数: " + totalConnections);
                    System.out.println("使用中的连接数: " + busyConnections);
                    System.out.println("空闲连接数: " + idleConnections);

                    Thread.sleep(2000); // 每 2 秒打印一次
                } catch (SQLException | InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }
}

输出

  1. 正常连接使用

    [连接池状态]
    总连接数: 5
    使用中的连接数: 3
    空闲连接数: 2
    
  2. 连接数耗尽报错

    尝试获取第 11 个连接...
    连接数不足,无法获取更多连接!
    com.mchange.v2.resourcepool.CannotAcquireResourceException: A resource pool could not acquire a resource ...
    
  3. 释放连接后连接池恢复

    [连接池状态]
    总连接数: 5
    使用中的连接数: 0
    空闲连接数: 5
    

注意

  • 根据实际情况调整 maxPoolSizeacquireIncrement 参数,避免频繁的连接创建和销毁。
  • 如果数据库连接数不足,检查数据库的 max_connections 配置是否满足需求。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值