1.数据库连接池原理:
2.自定义一个普通数据库连接池的实现:
属性:连接数据库的相关属性-Driver,url,name,password
连接池的相关参数-init(初始化连接池个数),max(连接池最大连接数),current(当前连接数)
List(连接池)
方法:getConnection(返回池子中的连接)
releaseConnection(将连接放回到池子)
首先建立一个库dbutils,和一个test表
代码实现:
-
public class DBPool {
-
// 定义连接数据库的参数
-
-
String driverclass = "com.mysql.jdbc.Driver";
-
String url = "jdbc:mysql:///dbutils";
-
String name = "root";
-
String psw = "root";
-
// 定义存储连接的集合
-
-
public LinkedList<Connection> pool = new LinkedList<Connection>();
-
// 定义池子相关的变量
-
-
int init_connection_count = 5;
-
int max_connection_count = 10;
-
int currrent_connection_count = 0;
-
// 定义构造函数进行初始化容量的设置
-
-
public DBPool() {
-
try {
-
for (int i = 0; i < init_connection_count; i++) {
-
Connection conn = creatConnection();
-
pool.add(conn);
-
currrent_connection_count++;
-
}
-
} catch (Exception e) {
-
System.out.println(e.getMessage());
-
System.out.println("初始化连接池失败");
-
throw new RuntimeException("初始化连接池失败");
-
}
-
}
-
private Connection creatConnection() throws Exception {
-
// 加载驱动
-
-
Class.forName(driverclass);
-
// 获取连接
-
-
Connection conn = DriverManager.getConnection(url, name, psw);
-
return conn;
-
}
-
// 提供一个public的返回池子连接的方法
-
-
-
public Connection getConnection() throws Exception {
-
// 判断池子中是否有连接
-
-
if (pool.size() > 0) {
-
return this.pool.removeFirst();
-
}
-
// 判断是否到达池子的最大容量
-
-
if (currrent_connection_count < max_connection_count) {
-
currrent_connection_count++;
-
return creatConnection();
-
}
-
// 池子到了最大的容量
-
-
throw new RuntimeException("池子到了最大容量了");
-
}
-
// 提供一个释放连接的方法
-
-
public void releaseConnection(Connection conn) {
-
try {
-
if (pool.size() < max_connection_count) {
-
this.pool.addLast(conn);
-
} else {
-
// 超过的连接关闭
-
-
conn.close();
-
}
-
} catch (Exception e) {
-
System.out.println(e.getMessage());
-
System.out.println("释放连接失败");
-
throw new RuntimeException("释放连接失败");
-
}
-
}
-
-
public static void main(String[] args) throws Exception {
-
DBPool pool = new DBPool();
-
System.out.println(pool.pool.size()); //5
-
-
Connection conn = pool.getConnection();
-
System.out.println(pool.pool.size()); //4
-
-
-
String SQL = "insert into test(name) values(?)";
-
PreparedStatement state = conn.prepareStatement(SQL);
-
state.setString(1, "scoield");
-
state.executeUpdate();
-
pool.releaseConnection(conn);
-
System.out.println(pool.pool.size()); //5
-
-
}
-
}
-------------------------------------------------------------------------------上面的代码会产生两个问题---------------------------------------------------------------------------------------
1.如果将获取到的Connection关闭,在释放连接,就没有意义了
解决方案:使用代理方式,拦截Connection的close方法
creatConnection()方法代码改进:
-
private Connection creatConnection() throws Exception {
-
// 加载驱动
-
-
Class.forName(driverclass);
-
// 获取连接
-
-
final Connection conn = DriverManager.getConnection(url, name, psw);
-
Connection proxy = (Connection)Proxy.newProxyInstance(
-
conn.getClass().getClassLoader(),
-
new Class[]{Connection.class},
-
new InvocationHandler() {
-
Object obj = null;
-
public Object invoke(Object proxy, Method method, Object[] params)
-
throws Throwable {
-
// 判断用户是否调用close方法
-
-
if ("close".equals(method.getName())) {
-
DBPool.this.releaseConnection(conn);
-
System.out.println("被代理对象拦截并重写了close方法");
-
}else {
-
obj = method.invoke(conn, params);
-
}
-
return obj;
-
}
-
});
-
return proxy;
-
}
2.线程安全问题
解决方案:加锁
代码优化:
-
public Connection getConnection()throws Exception{
-
// 同步连接池
-
-
synchronized (this.pool) {
-
// 判断池子中是否有连接
-
-
if(this.pool.size() > 0){
-
return this.pool.removeFirst();
-
}
-
// 判断是否到达池子的最大容量
-
-
if(this.current_connection_count < this.max_connection_count){
-
this.current_connection_count++;
-
return createConnection();
-
}
-
}
-
// 池子到了最大的容量
-
-
throw new Exception("池子到了最大的容量了!");
-
}
阅读(2779) | 评论(0) | 转发(0) |