深入分析连接池技术
模拟实现数据库连接池
1.首先我们用LinkedList来实现一个简单的连接池
这里用LinkedList很重要,下面会讲解。
模拟数据库连接池的操作流程:
-
创建一个数据库连接池
-
初始10个连接对象
-
来一个客户端,从连接池里取
-
当客户用完了,则不是真的销毁,而是放入到连接池中
模拟连接池的操作 * */ import java.sql.Connection; import java.util.LinkedList; import com.qf.utils.DBUtils; public class FastConnectPool { //步骤: // 1.创建一个数据库连接池 // 2.初始10个连接对象---放入集合(池) //3.回收连接放入连接池 //使用linkedlist,调用它内部派生的方法 public static LinkedList<Connection> list = new LinkedList<Connection>(); //注意:这里没有使用多态,而是用LinkedList引用来接受对象 //因为用list对象来接收LinkedList对象的话,就只能使用List接口定义的方法, //而无法使用LinkedList内部派生的方法 //即removefirst方法和addlast方法,分别用来实现获取连接和回收连接 static { for (int i = 0; i < 10; i++) { list.add(DBUtils.getConnection()); } } public Connection getConnection() { //1.判断池子中是否有连接对象;没有则重新创建连接池 //2.判断是否超出了最大连接数 //3.判断是否超时 //判断略 return list.removeFirst(); //拿到元素,并从集合中移除 } //回收 把连接对象添加到集合最后一个 public void release(Connection conn) { list.addLast(conn); //在集合最后添加连接对象 }
}
上面已经完成了一个简单的连接池了,赶紧来测试一下
import java.sql.Connection;
public class Test {
public static void main(String[] args) {
FastConnectPool pool = new FastConnectPool();
System.out.println(FastConnectPool.list.size());
Connection conn = pool.getConnection();
System.out.println(FastConnectPool.list.size());
//如何回收
pool.release(conn); //把conn添加到连接池链表的末尾
System.out.println(FastConnectPool.list.size());
}
}
2.实现DataSource规范
为什么要实现DataSource规范呢,DataSource规范又是什么呢?
连接池各有各的实现方式,所以sun公司定义了一个标准,DataSource接口
为什么要建立标准?
因为不同的连接池有不同实现,不方便管理。
更换连接池时,需要一个一个去更改所有连接池对象,代码变动太大而且麻烦。
前面所学的DBCP连接池,就是遵循了接口DataSource规范,所以我们自定义的连接池也同样要遵循sum公司提出的规范。
那么我们只要在FastConnectPool后面写上implements DataSource并用eclipse的提示重写接口方法就行了。
那么问题来了,既然我们要实现DataSource规范
即 FastConnectPool pool = new FastConnectPool();
要改成 DataSource dataSource = new FastConnectPool();
但是因为DataSource接口是没有定义release方法的,release方法是我们自己写的,所以我们之前写的release方法就调用不了了。
那么我们该如何实现回收连接对象呢?
直接调用close方法吗?
显然不行,这样会直接关闭连接对象而不是回收。
那么何不尝试重写close方法呢(注:前面已经说过自己写的方法,会因为接口中未定义而无法调用,故需重写接口中定义的方法)
具体实现:
自定义一个ConnectionWrapper类(Java中已有该类,但我们使用的是我们自己定义的,别点错了)
public class ConnectionWrapper implements Connection{
private LinkedList<Connection> list;
private Connection conn;
public ConnectionWrapper(LinkedList<Connection> list, Connection conn) {
this.list = list;
this.conn = conn;
}
//下略自动重写方法
}
修改getConnection方法
public Connection getConnection() {
Connection conn = list.removeFirst();
ConnectionWrapper cWrapper = new ConnectionWrapper(list,conn);
return cWrapper; //拿到元素,并从集合中移除
}
测试:
public class Test {
public static void main(String[] args) throws SQLException {
DataSource dataSource = new FastConnectPool();
Connection conn = dataSource.getConnection();
//dataSource.release(); err 实现类派生的方法不能调用
String sql = "select * from t_user";
PreparedStatement prst = conn.prepareStatement(sql);
ResultSet rs = prst.executeQuery();
while(rs.next()){
System.out.println(rs.getInt(1)+rs.getString(2)+rs.getString(3));
}
conn.close(); //直接会关闭连接对象---->重写使其变为回收
}
}