首先我们需要知道,在执行构造方法之前会优先执行代码块
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();
}
}
}
}