• 数据源和连接池


    数据源

      从接触DBMS開始就在用数据源(DataSource),它当中非常重要的一个作用就是能够管理Connection,管理的方式也就是常常听到的ConnectionPool。它的管理事实上就是对DriverManager获取Connection进行了包装。

      以下就首先看看用DataSource来代替DriverManager来获取Connection的优点:

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

     

    连接池

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

       1.注冊驱动

       2.建立连接

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

       4.运行语句

       5.处理运行结果

       6.释放资源

      上面的过程事实上就是client与DBserver交互的过程。

    这个过程就像两个人隔着一条河想要交流一样,当中最费时间的莫过于属搭桥的过程了。

    上面第二步“建立连接”的过程也就是搭桥的过程了。

      所以。创建Connection就相当于建一座桥。是数据库操作中最耗时的。所以用完以后就关掉是非常浪费的。

    如今,创建完以后将它放到集合中(arrayListlinkList),用的时候从集合中取,用完了还放回集合中,这样连接就能够复用了。就是用一个集合容器来缓存Connection对象。

      上面说的集合事实上就是连接池了,连接池可以理解成一个可以存放ConnectionCollection,有两种形式,即arrayListlinkList

    arrayList实际为一个数组。訪问速度非常快;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对象。而请求连接数小于最大连接数,则创建一个新的Connection
    			if (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,并用代码简单模它制定了它的原理。这也是深化审查和它的旧知识的过程的理解。

    版权声明:本文博主原创文章,博客,未经同意不得转载。

  • 相关阅读:
    高性能MySQL笔记(第十一章 可扩展的MySQL)01
    高性能MySQL笔记(第十章 复制)02
    高性能MySQL笔记(第十章 复制)01
    高性能MySQL笔记(第六章 查询性能优化) 02
    高性能MySQL笔记(一个奇怪的问题)
    高性能MySQL笔记(第六章 查询性能优化) 01
    高性能MySQL笔记(第五章 创建高性能的索引) 02
    高性能MySQL笔记(第五章 创建高性能的索引) 01
    [Luogu] P1438 无聊的数列 | 线段树简单题
    [UCF HSPT 2021] Sharon’s Sausages | 思维 暴力
  • 原文地址:https://www.cnblogs.com/mengfanrong/p/4905529.html
Copyright © 2020-2023  润新知