JDBC (Java DataBase Connectivity)数据库连接池原理解析与实现
一、应用程序直接获取数据库连接的缺点
用户每次请求都需要向数据库获得链接,而数据库创建连接通常需要消耗相对较大的资源,创建时间也较长。假设网站一天10万访问量,数据库服务器就需要创建10万次连接,极大的浪费数据库的资源,并且极易造成数据库服务器内存溢出、拓机。
二、使用数据库连接池优化程序性能
数据库连接池的基本概念
数据库连接是一种关键的有限的昂贵的资源,这一点在多用户的网页应用程序中体现的尤为突出.对数据库连接的管理能显著影响到整个应用程序的伸缩性和健壮性,影响到程序的性能指标.数据库连接池正式针对这个问题提出来的.数据库连接池负责分配,管理和释放数据库连接,它允许应用程序重复使用一个现有的数据库连接,而不是重新建立一个。
数据库连接池在初始化时将创建一定数量的数据库连接放到连接池中, 这些数据库连接的数量是由最小数据库连接数来设定的.无论这些数据库连接是否被使用,连接池都将一直保证至少拥有这么多的连接数量.连接池的最大数据库连接数量限定了这个连接池能占有的最大连接数,当应用程序向连接池请求的连接数超过最大连接数量时,这些请求将被加入到等待队列中.
数据库连接池的最小连接数和最大连接数的设置要考虑到以下几个因素:
最小连接数:是连接池一直保持的数据库连接,所以如果应用程序对数据库连接的使用量不大,将会有大量的数据库连接资源被浪费.
最大连接数:是连接池能申请的最大连接数,如果数据库连接请求超过次数,后面的数据库连接请求将被加入到等待队列中,这会影响以后的数据库操作
如果最小连接数与最大连接数相差很大:那么最先连接请求将会获利,之后超过最小连接数量的连接请求等价于建立一个新的数据库连接.不过,这些大于最小连接数的数据库连接在使用完不会马上被释放,他将被放到连接池中等待重复使用或是空间超时后被释放.
编写数据库连接池
DBManage 这个类用来读取properties配置文件,创建connection对象,管理connection对象
import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties; import orm.bean.Configuration;
import orm.pool.DBConnPool; /**
* 根据配置信息,维持连接对象的管理
* @author Haidnor
*
*/
@SuppressWarnings("all")
public class DBManage {
/**
* 配置信息
*/
private static Configuration conf; /**
* 连接池对象
*/
private static DBConnPool pool = null;
/**
* 初始化,加载指定的文件
*/
static {
Properties pros = new Properties(); try {
pros.load(Thread.currentThread().getContextClassLoader().getSystemResourceAsStream("database.properties"));
} catch (IOException e) {
e.printStackTrace();
}
conf = new Configuration(); //读取配置文件,将配置文件内的信息保存在配置对象中
conf.setDriver(pros.getProperty("driver"));
conf.setUrl(pros.getProperty("url"));
conf.setUser(pros.getProperty("user"));
conf.setPassword(pros.getProperty("password"));
conf.setUsingDB(pros.getProperty("usingDB"));
conf.setSrcPath(pros.getProperty("srcPath"));
conf.setPoPackage(pros.getProperty("poPackage"));
conf.setQueryClass(pros.getProperty("queryClass"));
conf.setPoolMinSize(Integer.parseInt(pros.getProperty("poolMinSize")));
conf.setPoolMaxSize(Integer.parseInt(pros.getProperty("poolMaxSize")));
} /**
* 在连接池中获得Connection对象
* @return
*/
public static Connection getConnetion() {
if(pool == null) {
pool = new DBConnPool();
}
return pool.getConnection();
} /**
* 创建新的Connection对象
* @return
*/
public static Connection createConnetion() {
try {
Class.forName(conf.getDriver());
return DriverManager.getConnection(conf.getUrl(),conf.getUser(),conf.getPassword()); //目前直接建立连接,后期加入连接池处理,提高效率
} catch (Exception e) {
e.printStackTrace();
return null;
}
} /**
* 关闭数据库连接ResultSet Statement Connection
* @param rs
* @param pa
* @param conn
*/
public static void close(ResultSet rs,Statement pa,Connection conn){
if(conn != null){
pool.close(conn);
}
} /**
* 返回Configuration对象
* @return Configuration对象
*/
public static Configuration getConf(){
return conf;
}
}
数据库连接池类DBManage ,将多个Connection对象存放在一个List集合中。在程序初始化前,会自动根据配置文件中设置的连接池对象最小数,往list集合中创建多个Connection对象。
以后使用Connection对象就可以直接从list集合中获取。关闭Connection对象不再使用close()方法,而是将Connection对象再放回到list集合中。
import java.sql.Connection;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List; import orm.core.DBManage; /**
* 连接池类
* @author Haidnor
*
*/ public class DBConnPool { /**
* 连接池对象
*/
private List<Connection> pool; /**
* 最大连接数
*/
private static final int POOL_MAX_SIZE = DBManage.getConf().getPoolMaxSize(); /**
* 最小连接数
*/
private static final int POOL_MIN_SIZE = DBManage.getConf().getPoolMinSize(); /**
* 初始化连接池,使池中的连接数达到最小值
*/
private void initPool() {
if(pool == null) {
pool = new ArrayList<Connection>();
}
while(pool.size() <= DBConnPool.POOL_MIN_SIZE){
pool.add(DBManage.createConnetion());
}
} /**
* 从连接池中取出一个连接对象
* @return
*/
public synchronized Connection getConnection() {
int last_index = pool.size() - 1;
Connection connection = pool.get(last_index);
pool.remove(last_index);
return connection;
} /**
* 将连接放回池中
*/
public synchronized void close(Connection connection) {
if(pool.size() >= POOL_MAX_SIZE){
try {
if(connection != null){
connection.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}else{
pool.add(connection);
}
} public DBConnPool(){
initPool();
} }
最后建立一个测试类。分别使用数据库连接池Connection对象和直接new Connection对象对数据库某个表进行3000次查询测试
使用连接池耗时952毫秒,不用连接池耗时12742毫秒。
import java.util.List; import orm.core.MySqlQuery;
import orm.po.User_yinbiao1; public class Test {
//不加连接池耗时 12742毫秒
//加连接池耗时:952毫秒
public static void main(String[] args) {
long a = System.currentTimeMillis();
for(int i=0; i<3000; i++){
testQueryRows();
}
long b = System.currentTimeMillis();
System.out.println("使用数据库连接池运行时间:" + (b - a) + "毫秒");
} public static void testQueryRows() {
List list = new MySqlQuery().queryRows("SELECT * FROM user_yinbiao1", User_yinbiao1.class, new Object[] {});
User_yinbiao1 user = (User_yinbiao1)list.get(2);
} }
JDBC (Java DataBase Connectivity)数据库连接池原理解析与实现的更多相关文章
- JDBC(Java Database Connectivity,Java数据库连接)API是一个标准SQL(Structured Query Language
JDBC(Java Database Connectivity,Java数据库连接)API是一个标准SQL(Structured Query Language,结构化查询语言)数据库访问接口,它使数据 ...
- [19/05/06-星期一] JDBC(Java DataBase Connectivity,java数据库连接)_基本知识
一.概念 JDBC(Java Database Connectivity)为java开发者使用数据库提供了统一的编程接口,它由一组java类和接口组成.是java程序与数据库系统通信的标准API. J ...
- SpringBoot 2.0 中 HikariCP 数据库连接池原理解析
作为后台服务开发,在日常工作中我们天天都在跟数据库打交道,一直在进行各种CRUD操作,都会使用到数据库连接池.按照发展历程,业界知名的数据库连接池有以下几种:c3p0.DBCP.Tomcat JDBC ...
- [19/05/05-星期日] JDBC(Java DataBase Connectivity,java数据库连接)_mysql基本知识
一.概念 (1).是一种开放源代码的关系型数据库管理系统(RDBMS,Relational Database Management System):目前有很多大公司(新浪.京东.阿里)使用: (2). ...
- [19/05/07-星期二] JDBC(Java DataBase Connectivity)_CLOB(存储大量的文本数据)与BLOB(存储大量的二进制数据)
一. CLOB(Character Large Object ) – 用于存储大量的文本数据 – 大字段有些特殊,不同数据库处理的方式不一样,大字段的操作常常是以流的方式来处理的.而非一般的字段,一次 ...
- [19/05/08-星期三] JDBC(Java DataBase Connectivity)_ORM(Object Relationship Mapping, 对象关系映射)
一.概念 基本思想: – 表结构跟类对应: 表中字段和类的属性对应:表中记录和对象对应: – 让javabean的属性名和类型尽量和数据库保持一致! – 一条记录对应一个对象.将这些查询到的对象放到容 ...
- JAVA和C#中数据库连接池原理与应用
JAVA和C#中数据库连接池原理 在现在的互联网发展中,高并发成为了主流,而最关键的部分就是对数据库操作和访问,在现在的互联网发展中,ORM框架曾出不穷, 比如:.Net-Core的EFCore.Sq ...
- JDBC数据库连接池原理
JDBC是java数据库连接的简称.它是一种用于实行SQL语句的Java API,可以为多种关系数据库提供统一访问,它由一组用java语言编写的类和接口组成.其相关的API都在java.sql.*包下 ...
- Java数据库连接池原理与简易实现
1.什么是数据库连接池 我们现在在开发中一定都会用到数据库,为了提高我们的系统的访问速度,数据库优化是一个有效的途径.我们现在开发中使用数据库一般都要经历以下的四个步骤:(1)加载数据库的驱动类,(2 ...
随机推荐
- sql server中实现mysql的find_in_set函数
charindex(','+'test'+',',','+Picture+',')>0
- 实时监控服务器某个端口状态TCPing
在给客户做运维服务期间,发现了一个奇怪的现象:备份系统(第三方国产)告警日志显示,每天晚上备份服务器的客户端在3点左右离线然后上线,再离线再上线,每晚两次,很是诡异. 联系了厂家技术支持,前后花了两天 ...
- 「网络流 24 题」最长 k 可重区间集
给定区间集合$I$和正整数$k$, 计算$I$的最长$k$可重区间集的长度. 区间离散化到$[1,2n]$, $S$与$1$连边$(k,0)$, $i$与$i+1$连边$(k,0)$, $2n$与$T ...
- html中script标签使用async属性和defer属性的区别
相同点: 首先async和defer只对header里的外连脚本script标签上起作用,如果script标签是放在header外或者是header里的内置脚本以及动态生成的script标签是不起作用 ...
- 旋转动画(RotateTransform)
Silverlight的基础动画包括偏移.旋转.缩放.倾斜和翻转动画,这些基础动画毫无疑问是在Silverlight中使用得最多的动画效果,其使用也是非常简单的.相信看过上一篇<偏移动画(Tra ...
- LeetCode 腾讯精选50题--合并K个排序链表
今天的题目稍微有点复杂了,因为是K个有序链表的合并,看到这道题后的大体思路是这样的: 1.首先先做到两个链表的合并,链表的合并我想到的是用递归操作, 2.其次是多个链表的合并,所以在第一步实现的基础上 ...
- UART串口简介
通用异步收发传输器(Universal Asynchronous Receiver Transmitter) 原理 发送数据时,CPU将并行数据写入UART,UART按照一定的格式在一根电线上串行发出 ...
- 如何上传HTML5应用到SAP云平台的Cloud Foundry环境下
先使用WebIDE创建一个HTML5应用.New->Project from Template: 从可选模板里选择SAPUI5 Application: 创建一个HTML5 Module,取名为 ...
- 【转】Delphi货币类型转中文大写金额
unit TU2.Helper.Currency; interface ): string; ): string; implementation uses System.SysUtils, Syste ...
- 生成ID之雪花算法
package com.shopping.test; /** * SnowFlake的结构如下(每部分用-分开):<br> * 0 - 0000000000 0000000000 0000 ...