数据库连接池学习

一、应用程序直接获取数据库连接的缺点

  用户每次请求都需要向数据库获得链接,而数据库创建连接通常需要消耗相对较大的资源,创建时间也较长。假设网站一天10万访问量,数据库服务器就需要创建10万次连接,极大的浪费数据库的资源,并且极易造成数据库服务器内存溢出、拓机。如下图所示:

  

二、使用数据库连接池优化程序性能

2.1、数据库连接池的基本概念

  数据库连接是一种关键的有限的昂贵的资源,这一点在多用户的网页应用程序中体现的尤为突出.对数据库连接的管理能显著影响到整个应用程序的伸缩性和健壮性,影响到程序的性能指标.数据库连接池正式针对这个问题提出来的.数据库连接池负责分配,管理和释放数据库连接,它允许应用程序重复使用一个现有的数据库连接,而不是重新建立一个。如下图所示:

  

       数据库连接池在初始化时将创建一定数量的数据库连接放到连接池中, 这些数据库连接的数量是由最小数据库连接数来设定的.无论这些数据库连接是否被使用,连接池都将一直保证至少拥有这么多的连接数量.连接池的最大数据库连接数量限定了这个连接池能占有的最大连接数,当应用程序向连接池请求的连接数超过最大连接数量时,这些请求将被加入到等待队列中.

       数据库连接池的最小连接数和最大连接数的设置要考虑到以下几个因素:

  1. 最小连接数:是连接池一直保持的数据库连接,所以如果应用程序对数据库连接的使用量不大,将会有大量的数据库连接资源被浪费.
  2. 最大连接数:是连接池能申请的最大连接数,如果数据库连接请求超过次数,后面的数据库连接请求将被加入到等待队列中,这会影响以后的数据库操作
  3. 如果最小连接数与最大连接数相差很大:那么最先连接请求将会获利,之后超过最小连接数量的连接请求等价于建立一个新的数据库连接.不过,这些大于最小连接数的数据库连接在使用完不会马上被释放,他将被放到连接池中等待重复使用或是空间超时后被释放.

2.2、编写数据库连接池

  编写连接池需实现java.sql.DataSource接口。DataSource接口中定义了两个重载的getConnection方法:

  • Connection getConnection()
  • Connection getConnection(String username, String password)

  实现DataSource接口,并实现连接池功能的步骤:

  1. 在DataSource构造函数中批量创建与数据库的连接,并把创建的连接加入LinkedList对象中。
  2. 实现getConnection方法,让getConnection方法每次调用时,从LinkedList中取一个Connection返回给用户。
  3. 当用户使用完Connection,调用Connection.close()方法时,Collection对象应保证将自己返回到LinkedList中,而不要把conn还给数据库。Collection保证将自己返回到LinkedList中是此处编程的难点

 数据库连接池核心代码

  使用动态代理技术构建连接池中的connection

复制代码
 1 proxyConn = (Connection) Proxy.newProxyInstance(this.getClass()
 2             .getClassLoader(), conn.getClass().getInterfaces(),
 3 new InvocationHandler() {  4 //此处为内部类,当close方法被调用时将conn还回池中,其它方法直接执行  5 public Object invoke(Object proxy, Method method,  6 Object[] args) throws Throwable {  7 if (method.getName().equals("close")) {  8  pool.addLast(conn);  9 return null; 10  } 11 return method.invoke(conn, args); 12  } 13 });
复制代码

数据库连接池编写范例:

复制代码
  1 package me.gacl.demo;
  2 
  3 import java.io.InputStream;  4 import java.io.PrintWriter;  5 import java.lang.reflect.InvocationHandler;  6 import java.lang.reflect.Method;  7 import java.lang.reflect.Proxy;  8 import java.sql.Connection;  9 import java.sql.DriverManager;  10 import java.sql.SQLException;  11 import java.util.LinkedList;  12 import java.util.Properties;  13 import javax.sql.DataSource;  14  15 /**  16 * @ClassName: JdbcPool  17 * @Description:编写数据库连接池  18 * @author: 孤傲苍狼  19 * @date: 2014-9-30 下午11:07:23  20 *  21 */  22 public class JdbcPool implements DataSource{  23  24 /**  25  * @Field: listConnections  26  * 使用LinkedList集合来存放数据库链接,  27  * 由于要频繁读写List集合,所以这里使用LinkedList存储数据库连接比较合适  28 */  29 private static LinkedList<Connection> listConnections = new LinkedList<Connection>();  30  31 static{  32 //在静态代码块中加载db.properties数据库配置文件  33 InputStream in = JdbcPool.class.getClassLoader().getResourceAsStream("db.properties");  34 Properties prop = new Properties();  35 try {  36  prop.load(in);  37 String driver = prop.getProperty("driver");  38 String url = prop.getProperty("url");  39 String username = prop.getProperty("username");  40 String password = prop.getProperty("password");  41 //数据库连接池的初始化连接数大小  42 int jdbcPoolInitSize =Integer.parseInt(prop.getProperty("jdbcPoolInitSize"));  43 //加载数据库驱动  44  Class.forName(driver);  45 for (int i = 0; i < jdbcPoolInitSize; i++) {  46 Connection conn = DriverManager.getConnection(url, username, password);  47 System.out.println("获取到了链接" + conn);  48 //将获取到的数据库连接加入到listConnections集合中,listConnections集合此时就是一个存放了数据库连接的连接池  49  listConnections.add(conn);  50  }  51  52 } catch (Exception e) {  53 throw new ExceptionInInitializerError(e);  54  }  55  }  56  57  @Override  58 public PrintWriter getLogWriter() throws SQLException {  59 // TODO Auto-generated method stub  60 return null;  61  }  62  63  @Override  64 public void setLogWriter(PrintWriter out) throws SQLException {  65 // TODO Auto-generated method stub  66  67  }  68  69  @Override  70 public void setLoginTimeout(int seconds) throws SQLException {  71 // TODO Auto-generated method stub  72  73  }  74  75  @Override  76 public int getLoginTimeout() throws SQLException {  77 // TODO Auto-generated method stub  78 return 0;  79  }  80  81  @Override  82 public <T> T unwrap(Class<T> iface) throws SQLException {  83 // TODO Auto-generated method stub  84 return null;  85  }  86  87  @Override  88 public boolean isWrapperFor(Class<?> iface) throws SQLException {  89 // TODO Auto-generated method stub  90 return false;  91  }  92  93 /* 获取数据库连接  94  * @see javax.sql.DataSource#getConnection()  95 */  96  @Override  97 

转载于:https://www.cnblogs.com/myadmin/p/5309844.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值