APP下载

基于Java的数据库连接池技术的算法实现

2009-04-09罗金涛李跃新

新媒体研究 2009年5期
关键词:连接数据源

罗金涛 李跃新

[摘要]数据库连接池是一种非常高效实用的技术。对数据库连接池的基本实现原理进行分析,并给出初步的算法实现。

[关键词]数据源 连接池 连接 JAVA JDBC

中图分类号:TP3文献标识码:A文章编号:1671-7597(2009)0310052-02

一、引言

在任何的项目开发过程中,都离不开对数据的操作,这一系列的动作最终都体现在底层和数据库的交互,在常规的jdbc数据库操作到时候,总是要反复的打开和关闭对数据库的连接,但是这个过程是一个相当消耗系统资源的过程,对于小的一般程序环境来说,似乎感觉不到性能的影响,但是对于一些多层结构大型企业级的应用程序环境来说,这种反复消耗系统资源的弊端就开始体现出来了。于是很多服务器产品都提供了连接池技术来提高数据库操作的性能,通过连接池技术,可以尽可能多对内存资源进行重用,大大节约了内存的开销,同时能够支持更多的客户服务和提高程序的运行效率,最终从整体上提高到了服务器的运行效率。

二、连接池的产生及基本原理

在早期的java项目开发过程中,当项目开发完成之后,运行的时候发现随着访问量的增长,系统的性能下降得特别的严重,实践表面,导致系统性能下降的原因就是发生在数据库访问阶段,而在此阶段,有一个反复执行的动作,那就是建立和关闭Connection对象,由于关闭操作是在所有的数据库动作执行之后才进行,它主要目的是释放资源,而建立Connection对象的操作是在加载了数据库驱动之后,数据库操作之前必须完成的动作,而且这个对象的生成过程比较耗时,如果每次操作数据库都临时生成一个Connection对象,那么随着并发访问量的增加,必然会影响系统的性能,所以Connection对象的生成就是影响系统性能的主要原因,为了解决这个瓶颈,一个普遍可行的解决方案,就是在应用启动的时候,一次性生成若干个Connection对象,而不是在每次操作数据库的时候去临时生成,这些一次性生成的若干个Connection对象就可以常驻内存中可以反复被使用,这样就避免了Connection对象的创建过程耗时的缺陷,从而使得数据库访问速度得到了很大的提升,瓶颈有效的得到了缓解,这就是数据库连接池技术的产生背景。

图1显示了数据库连接池技术的基本原理。

当客户端访问需要对数据库进行请求,需要先建立数据库的连接对象Connection,此时是向数据源对象(DataSource)进行请求,而数据源对象预先一次性和数据库(Database)建立好了若干个连接(Connection),并将这些连接组成一个连接池(Connection Pool),由应用程序动态的对连接池中的连接进行申请,使用和释放。当请求的对象用完以后,不需要进行关闭,直接返回给连接池当中,以便其他请求可以重复使用。当并发的请求的数量多于连接池的连接数的时候,这些请求先在排队请求队列当中排队等候,然后由应用程序根据连接池中的使用情况,动态的来增加连接数。

三、数据库连接池基本功能的算法实现

因为连接池的建立已经在它基础上的操作和对集合类型的操作非常相似,因此我们可以将整个实现过程通过对集合类型的对象操作来进行模拟实现,首先,我们要建立一个数据库连接池类ConnectionPool,为了控制在取得连接的过程中只生成一个类的实例,应该用单态模式(Singleton)来设计这个连接池类,通过单态模式可以节省内存的开销,同时也降低了Java虚拟机(JVM)进行垃圾回收的开销。首先需要定义一个私有的构造方法,然后通过保留一个公开的静态方法来取得这个类的实例,另外要有一个容器来保存生成的连接,在JAVA中,我们一般使用集合类型的对象,例如Vector,ArrayList都可以,但是考虑到多线程的安全性,我们一般使用Vector来进行封装,其中用到的代码片段如下:

首先定义一个名为ConnectionPool的类,里面用到的一系列属性和几个主要方法如下:

private Vector pool; //Vector类型的连接池对象

private String url; //数据库访问的url

private String username; //数据库访问的用户名

private String password; //数据库的密码

private String driver; //数据库的驱动类

private int poolSize; //连接池的大小,即连接的数量

private int initSize; //初始化连接的数量

private int poolSizeIncrement; //当连接数不够时的容量的增量

private static ConnectionPool instance=null; //定义一个静态的连接池类变量

//私有构造方法,读取属性文件的内容,建立指定数量的连接池中的初始连接。

private ConnectionPool(){

//读取初始化配置参数,我们可以将数据库参数保存在properties的属性文件中,或者在xml文件中加以配置,推荐使用xml方式,可以提高系统解耦。

… … … …

//实例化一个向量,当作数据库连接池对象的容器。

Vector pool=new Vector(poolSize, poolSizeIncrement);

//在连接池中创建指定数目的数据库连接对象

for(int i=0;i

try{

Class.forName(driver);

Connection conn=java.sql.DriverManager.

getConnection(url,username,password);

}catch (SQLException e) {

e.printStackTrace();

}catch (ClassNotFoundException e) {

e.printStackTrace();

}

//将生成的Connection对象放入Vector中

pool.add(conn);

}

}

//静态方法,用于初始化该连接池类的实例。

public static ConnectionPool getInstance(){

if(instance==null){

instance=new ConnectionPool();

}

return instance;

}

当我们通过上面的方法调用这个类的私有构造函数后,它就会根据配置文件中的参数,创建指定数量的数据库连接,如果有程序需要进行数据库访问,那么可以给它分配一个连接,因为所有的连接对象都保存在一个Vector中,对于每个需要取得连接的请求,首先就让它取得get(0)位置上连接对象,并将它从Vector中删除,从而保证Vector中剩下的都是可用的连接。相反,当一个连接用完以后,就应该释放这个连接,并且将这个刚刚释放的连接重新加入到连接池Vector中,其具体代码如下:

//返回连接池中的一个数据库连接,用户自己来调用以取得数据库的连接对象。

public synchronized Connection getConnection(){

if(pool.size()>0){

Connection conn=(Connection)pool.get(0);

//取得连接后,从连接池中删除

pool.remove(conn);

return conn;

}else{

return null;

}

}

//释放连接方法,需要用户自己来调用这个方法。

public synchronized void closeConnection(Connection conn){

//返回到连接池中,即将这个Conncetion对象加入到Vector中最前面。

pool.add(0,conn);

}

如果最后我们的要关闭所有的连接,那么就要直接关闭数据库连接池,那么可以通过遍历,依次连接池对象中的每个连接,同时可以从vector对象中移除,代码如下所示:

publicsynchronized void closePool(){

//通过遍历的方式依次关闭Conncetion对象

for(int i=0;i

try{

((Connection)pool.get(i)).close();

}catch(SQLException e){

e.printStackTrace();

}

//从Vector中移除

pool.remove(i);

}

}

以上就是基于数据库连接池技术的基本原理及用java代码的算法实现过程,当我们需要使用连接池技术时,首先我们通过ConnectionPool.getI

nstance()方法取得连接池实例,然后会自动调用私有的构造方法ConnectionPool()取得相应数据库连接参数,并在Vector中生成指定数目的Conncetion对象,在程序中我们就可以通过调用getConnection()方法来取得连接了,因为此时的连接不是临时生成的,而是在连接池初始化时就生成了,所以这个取得Conncetion对象的过程的效率非常高,最后我们可以调用closeConnection(Connection conn)和closePool()方法依次关闭Conncetion和连接池。测试表明,通过连接池技术的来访问数据库比不使用连接池技术时效率要高很多,当数据库访问量大时,采用连接池技术的优势更加明显。

目前可用的数据库连接池组件也很多,例如C3PO,DBCP,PROXOOL等都是一些优秀的连接池组件,我们只需要在程序中引入相关的类库,然后通过相关的参数配置或者实现相应的接口和方法,都可以很方便地在实际的项目中使用它们提供的数据库连接池技术了,另外在很多服务器中,如Tomcat,Jboss,WebLogic,WebSphere都内置提供了对数据库连接池的支持,例如在Tomcat中本身也带有连接池的功能,它是通过配置数据源(DataSource)参数来实现的连接池功能,通过在配置文件的相应位置加入如下代码 ,我们只需要设置好相关参数,就完成了对数据源(DataSource)的配置,然后在程序当中加入以下语句就可以取得数据源的连接了Context context = new InitialContext();

DataSource ds = (DataSource)context.lookup("");

con=ds.getConnection();

值得特别注意的是,有了这个连接,我们可以像平时一样操作数据库了,而且我们可以执行con.close();让连接池收回这个连接,但和普通连接不同的是,此时并没有关闭到数据库的物理连接,所以下次请求的时候不会重新生成新的连接,这也是使用连接池技术的好处,以上数据源的配置也是建立在连接池技术的基本原理之上的,例如,name,username,passw

Ord,driverClassName,url等参数实际上就是和数据库访问相关的参数,另外,maxActive代表最大连接数,maxIdle表示最大空闲数,maxWait代表最大等待数,这些额外的参数只是各个服务器厂商提供的连接池的额外属性。

四、结束语

本文是从数据库连接池最基本的原理着手,从最基本的层面分析了数据库连接池技术的核心原理,并用Java语言实现了核心代码,目前的数据库连接池组件很丰富,功能也各不相同,但是其核心原理都差不多,都是在数据库连接池技术的最基本的功能上的不断完善与创新。

参考文献:

[1]阎宏,Java与模式[M].北京:电子工业出版社,2002年10月.209-227.

[2]李刚,轻量级J2EE企业应用实战[M].北京:电子工业出版社,2007年04月.390-399.

[3]刘晓华、张健、周慧贞,JSP应用开发详解[M].北京:电子工业出版社,2007年07月.323-327.

作者简介:

罗金涛,男,汉族,湖北咸宁人,硕士,研究方向:人工智能,并行计算;李跃新,男,汉族,湖北武汉人,副教授,研究方向:人工智能,并行计算。

猜你喜欢

连接数据源
图表中的交互 数据钻取还能这么用
腾讯发挥“连接”优势助力区域品牌崛起
陈春花:什么样的公司最受90后欢迎?
基于Excel的照片查询系统开发与应用
再谈利用邮件合并功能批量生成准考证
数据有增加 图表自适应