数据源和连接池

来源:互联网 发布:弹弓淘宝网店铺 编辑:程序博客网 时间:2024/05/18 02:36

 

数据源

 

  从接触DBMS开始就在用数据源(DataSource),它其中很重要的一个作用就是可以管理Connection,管理的方式也就是经常听到的ConnectionPool。它的管理其实就是对DriverManager获取Connection进行了包装。

  下面就首先看看用DataSource来取代DriverManager来获取Connection的好处:

  一般DataSource内部会用一个连接池来缓存Connection,这样获得Connection速度很快,可以大幅度提高数据库的访问速度;通过它获得的Connection都是已经被包裹过的(不是驱动原来的连接),他的close方法已经被修改(并不是真正的关闭)。我们只需和DataSource打交道,不会直接访问连接池。

 

连接池

 

  前面博客讲了,操作数据库的一般步骤:

   1.注册驱动

   2.建立连接

   3.创建执行sql语句的对象

   4.执行语句

   5.处理执行结果

   6.释放资源

  上面的过程其实就是客户端与DB服务器交互的过程。这个过程就像两个人隔着一条河想要交流一样,其中最费时间的莫过于属搭桥的过程了。上面第二步“建立连接”的过程也就是搭桥的过程了。

  所以,创建Connection就相当于建一座桥,是数据库操作中最耗时的。所以用完以后就关掉是很浪费的。现在,创建完以后将它放到集合中(arrayListlinkList),用的时候从集合中取,用完了还放回集合中,这样连接就可以复用了。就是用一个集合容器来缓存Connection对象。

  上面说的集合其实就是连接池了,连接池可以理解成一个能够存放ConnectionCollection,有两种形式,即arrayListlinkListarrayList实际为一个数组,访问速度很快;linkList为一个链表,增、删速度比较快。而连接池中的Connection需要频繁的增删,所以采用linkList来作为Connection对象的容器集合。

  下面就用代码模拟一个DataSource内部的连接池:

import java.sql.Connection;import java.sql.DriverManager;import java.sql.SQLException;import java.util.LinkedList;/** * @author-zhipeng */public class MyDataSource {private static String url = "jdbc:mysql://localhost:3306/jdbc";private static String user = "root";private static String password = "";private static int initCount = 5;private static int maxCount = 10;private int currentCount = 0;//创建一个LinkedList作为Connection的容器LinkedList<Connection> connectionsPool = new LinkedList<Connection>();//初始,创建5个Connection对象放到LinkedList中,用的时候从链表头部取,不用了放到尾部public MyDataSource() {try {for (int i = 0; i < initCount; i++) {this.connectionsPool.addLast(this.createConnection());this.currentCount++;}} catch (SQLException e) {throw new ExceptionInInitializerError(e);}}//创建连接时就调用这个方法--从Connection链表容器头部取一个public Connection getConnection() throws SQLException {//枷锁-针对并发操作synchronized (connectionsPool) {//如果连接池(实际为LinkList)中还有Connection对象则取出一个if (this.connectionsPool.size() > 0)return this.connectionsPool.removeFirst();//如果连接池没有(初始为5个)Connection对象,而请求连接数小于最大连接数,则创建一个新的Connectionif (this.currentCount < maxCount) {this.currentCount++;return this.createConnection();}//否则抛出异常,超过最大连接数,没有连接可用throw new SQLException("已没有链接");}}//关闭连接时就调用这个方法--不是真正的释放连接,而是放到从Connection链表容器的尾部public void free(Connection conn) {this.connectionsPool.addLast(conn);}//创建Connection的根代码private Connection createConnection() throws SQLException {return DriverManager.getConnection(url, user, password);}}

  从上面的代码实现可知,如果超过Connection Pool的最大连接数(10个)则必然会因没有连接可以使用而抛异常,下面就用代码实验一下:

/** * @author-zhipeng */public class TestConnectionPool {private static DataSource myDataSource = null;/** * 循环创建11个Connection,期间都不释放(关闭) */public static void main(String[] args) throws Exception {for (int i = 0; i < 11; i++) {Connection conn = myDataSource.getConnection();System.out.println(conn);//JdbcUtils.free(null, null, conn);}}}

  然后运行,就会发现,当创建第11个的时候就会抛出异常:

 

 

 

  这也验证了我们上面的实现。当然还可以进行一系列其它的测试,比如创建五个再释放一个,然后再创建一个,这是你就会发现,Connection Pool的“队列”结构。

 

总结

 

  上面简单介绍了DataSource,和Connection Pool,并用代码简单模拟了它的原理。这也是对旧知识的温习和加深理解的过程吧。

0 0
原创粉丝点击