您的位置:首页 > 产品设计 > UI/UE

[数据库--druid连接池实现]--Java版本

2016-05-09 21:02 543 查看

前言

之前有介绍一篇关于自定义的数据库链接池实现,但是质量并不高。而且遭到博友的一脸嫌弃!确实,拿出来的东西就应该保证是正确的,或者质量高,否则很容易就误导了他人,显得TMD也不道德,所以今天专门重写之前的想法,当然,还有许多文章需要更新,后期我都会一一完善,希望对各位有一定的帮助。
目前针对Java web应用使用的数据库链接池比较多也很杂,但稳定且好用的还是推荐阿里巴巴的druid(德鲁伊连接池)。那么下面就重点介绍自定义链接池和使用阿里巴巴的durid连接池,不足指出请指正。

什么是连接池?

连接池是一种创建和维护JDBC连接对象集合的机制。维护连接对象池的主要目的是利用可重用性。只有在没有可用的连接对象时才会创建新的连接对象。这种技术可以提高应用程序的整体性能。本文将尝试展示如何将这种池化机制应用于Java应用程序。

为什么要用连接池?

建立数据库连接是一个非常耗费资源的过程,需要大量的开销。而且,在多线程环境下,打开和关闭连接会使情况变得更糟。要了解创建新数据库连接的每个请求可能发生的情况,请考虑以下几点。数据库连接使用的是成立的DriverManager的数据源对象。

应用程序可以调用getConnection()方法。
JDBC驱动程序请求一个JVM套接字。
JVM必须确保调用不会违反安全方面(小程序可能会出现这种情况)。
在进入网络云之前,调用可能需要通过防火墙渗透。
到达主机时,服务器处理连接请求。
数据库服务器初始化连接对象并返回到JDBC客户端(再次通过相同的过程)。
最后,我们得到一个连接对象。

这只是幕后实际情况的简单概述。放心吧,实际的过程比这个更加复杂和精细。在单线程控制的环境中,数据库事务大部分是线性的,比如打开连接,完成数据库事务,关闭连接。实际应用更复杂; 连接池的机制可以增加性能,尽管还有许多对于应用程序整体性能至关重要的其他属性。
连接池概念的复杂性在我们深入研究的过程中变得越来越难理解。但是,要感谢那些专门为连接池合作而制作图书馆的人们。这些库遵循JDBC的规范,并提供更简单的API来实际在Java应用程序中实现它们。

怎样使用连接池?

1、自定义链接池

连接池的管理用了享元模式,这里对连接池进行简单设计。

【一】、设计思路

(1).连接池配置属性DBbean:里面存放可以配置的一些属性
(2).连接池接口IConnectionPool:里面定义一些基本的获取连接的一些方法
(3).接口实现ConnectionPool:对上面操作进行实现,并加入一些其他方法
(4).连接池管理ConnectionPoolManager:管理所有的不同的连接池,所有的连接都能通过这里进行获得连接
(5).另外还有几个测试类,和连接信息模拟的类,这里就不进行xml 和配置文件信息的读取了

【二】、测试代码实现(数据库驱动版本是5.1.38、连接池版本是阿里巴巴druid-1.1.5)

代码目录结构:



(1)配置文件类
packagecom.yjf.java.bean;
importjava.io.Serializable;
/**
* Created by rooton 20170924.
* Update date:
* <p>
* Time: 1:50 PM
* Project:test-java
* Package:com.yjf.java.bean
* Describe :
* <p>
* Result of Test:test ok,test error
* Command:
* <p>
* <p>
* Email: jifei.yang@ngaa.com.cn
* Status:Using online
* Attention:
*/
publicclassDBInfoimplementsSerializable{
/* Connectionproperties */
privateStringdriverName;
privateStringurl;
privateStringuserName;
privateStringpassword;
privateStringpoolName;
privateIntegerinitConnections;
privateIntegermaxActiveConnections;
privatelongconnectionTimeOut ;
privatebooleanisCurrentConnection;
privatebooleanisCheckPool;
privatelonglazyCheck;
privatelongperiodCheck ;
privatelongreleaseConnTime;
privatelongdestroyConnTime;

publicDBInfo(){
}

publicDBInfo(StringdriverName,Stringurl,StringuserName,Stringpassword,StringpoolName,IntegerinitConnections,IntegermaxActiveConnections,longconnectionTimeOut,booleanisCurrentConnection,booleanisCheckPool,longlazyCheck,longperiodCheck,longreleaseConnTime,longdestroyConnTime){
this.driverName=driverName;
this.url=url;
this.userName=userName;
this.password=password;
this.poolName=poolName;
this.initConnections=initConnections;
this.maxActiveConnections=maxActiveConnections;
this.connectionTimeOut=connectionTimeOut;
this.isCurrentConnection=isCurrentConnection;
this.isCheckPool=isCheckPool;
this.lazyCheck=lazyCheck;
this.periodCheck=periodCheck;
this.releaseConnTime=releaseConnTime;
this.destroyConnTime=destroyConnTime;
}

publicStringgetDriverName(){
returndriverName;
}

publicvoidsetDriverName(StringdriverName){
this.driverName=driverName;
}

publicStringgetUrl(){
returnurl;
}

publicvoidsetUrl(Stringurl){
this.url=url;
}

publicStringgetUserName(){
returnuserName;
}

publicvoidsetUserName(StringuserName){
this.userName=userName;
}

publicStringgetPassword(){
returnpassword;
}

publicvoidsetPassword(Stringpassword){
this.password=password;
}

publicStringgetPoolName(){
returnpoolName;
}

publicvoidsetPoolName(StringpoolName){
this.poolName=poolName;
}

publicIntegergetInitConnections(){
returninitConnections;
}

publicvoidsetInitConnections(IntegerinitConnections){
this.initConnections=initConnections;
}

publicIntegergetMaxActiveConnections(){
returnmaxActiveConnections;
}

publicvoidsetMaxActiveConnections(IntegermaxActiveConnections){
this.maxActiveConnections=maxActiveConnections;
}

publiclonggetConnectionTimeOut(){
returnconnectionTimeOut;
}

publicvoidsetConnectionTimeOut(longconnectionTimeOut){
this.connectionTimeOut=connectionTimeOut;
}

publicbooleanisCurrentConnection(){
returnisCurrentConnection;
}

publicvoidsetCurrentConnection(booleancurrentConnection){
isCurrentConnection=currentConnection;
}

publicbooleanisCheckPool(){
returnisCheckPool;
}

publicvoidsetCheckPool(booleancheckPool){
isCheckPool=checkPool;
}

publiclonggetLazyCheck(){
returnlazyCheck;
}

publicvoidsetLazyCheck(longlazyCheck){
this.lazyCheck=lazyCheck;
}

publiclonggetPeriodCheck(){
returnperiodCheck;
}

publicvoidsetPeriodCheck(longperiodCheck){
this.periodCheck=periodCheck;
}

publiclonggetReleaseConnTime(){
returnreleaseConnTime;
}

publicvoidsetReleaseConnTime(longreleaseConnTime){
this.releaseConnTime=releaseConnTime;
}

publiclonggetDestroyConnTime(){
returndestroyConnTime;
}

publicvoidsetDestroyConnTime(longdestroyConnTime){
this.destroyConnTime=destroyConnTime;
}
}

(2)连接池的接口类

packagecom.yjf.java.core;

importjava.sql.Connection;

/**
* Created by rooton 20170924.
* Update date:
* <p>
* Time: 2:39 PM
* Project:test-java
* Package:com.yjf.java.core
* Describe :
* <p>
* Result of Test:test ok,test error
* Command:
* <p>
* <p>
* Email: jifei.yang@ngaa.com.cn
* Status:Using online
* Attention:
*/
publicinterfaceIConnectionPool{
// 1\获得连接
ConnectiongetConnection();

// 2\获得当前连接
ConnectiongetCurrentConnecton();

// 3\回收连接
voidreleaseConn(Connectionconn);

// 4\连接池是活动状态
booleanisActive(BooleanisActiveNot);

// 5\定时器,检查连接池
voidcheackPool();

// 6\定时检查关闭未占用的链接。
voiddestroyFreeAndMoveToOther();

// 7\销毁那些长时间不用的链接。
voiddestroyLongTimeNotUseConn();
}

(3)连接池的实现类

packagecom.yjf.java.core;

importcom.yjf.java.bean.DBInfo;

importjava.sql.Connection;
importjava.sql.DriverManager;
importjava.sql.SQLException;
importjava.util.Timer;
importjava.util.TimerTask;
importjava.util.Vector;

/**
* Created by rooton 20170924.
* Update date:
* <p>
* Time: 2:39 PM
* Project:test-java
* Package:com.yjf.java.core
* Describe :
* <p>
* Result of Test:test ok,test error
* Command:
* <p>
* <p>
* Email: jifei.yang@ngaa.com.cn
* Status:Using online
* Attention:
*/
publicclassIConnectionPoolImplimplementsIConnectionPool{
privatestaticThreadLocal<Connection>threadLocal=newThreadLocal<>(); //
将线程和连接绑定,保证事务能统一执行
privateDBInfodbBean; //连接池配置属性
privateBooleanisActive=false; //连接池活动状态
privateIntegertotalConn=0; //记录创建的总的连接数
privateVector<Connection>freeConnection=newVector<>(); //
空闲连接
privateVector<Connection>activeConnection=newVector<>(); //
活动连接
privateVector<Connection>otherConnection=newVector<>();
// 其他连接

publicIConnectionPoolImpl(DBInfodbBean){
super();
this.dbBean=dbBean;
init();
cheackPool();
destroyFreeAndMoveToOther();
destroyLongTimeNotUseConn();
}

//连接池状态
publicbooleanisActive(BooleanisActiveNot){
isActive=isActiveNot;
returnisActive;
}

//初始化
privatevoidinit(){
try{
IntegerminConn=dbBean.getInitConnections();
//初始化最小连接数
System.out.println("Info:初始化最小连接数-->"+minConn);
for(inti=0;i<minConn;i++){
Connectionconn;
conn=newConnection();
if(conn!=null){
freeConnection.add(conn);
totalConn=totalConn+1;
}
}
//设置连接数据库池是活动的。
isActive=true;
}catch(Exceptione){
e.printStackTrace();
}
}

//获得当前连接
publicConnectiongetCurrentConnecton(){
//默认线程里面取
Connectionconn=threadLocal.get();
if(!isValid(conn)){
conn=getConnection();
}
returnconn;
}

//获得连接
publicsynchronizedConnectiongetConnection(){
Connectionconn=null;
try{
//判断是否超过最大连接数限制
if(totalConn<this.dbBean.getMaxActiveConnections()){
IntegerfreeSize=freeConnection.size();
IntegerotherSize=otherConnection.size();
if(freeSize>0||otherSize>0){

intindex=0;
//判断是从空闲链接中获取链接,还是从其他链接中获取conn。
if(freeSize>0){
conn=freeConnection.get(index);

if(conn!=null){
threadLocal.set(conn);
}
//移除一个链接,则需要添加一个链接到Vector中。
activeConnection.add(conn);
freeConnection.remove(index);
}else{
conn=otherConnection.get(index);
if(conn!=null){
threadLocal.set(conn);
}
//移除一个链接,则需要添加一个链接到Vector中。
activeConnection.add(conn);
otherConnection.remove(index);
}

}else{
conn=newConnection();
activeConnection.add(conn);
totalConn++;
}
System.out.println("Info:空闲链接的数量-->"+freeConnection.size());
System.out.println("Info:其他链接的数量-->"+otherConnection.size());
}else{
//继续获得连接,直到从新获得连接
System.out.println("Info:等待获取新的链接。");
wait(this.dbBean.getConnectionTimeOut());
conn=getConnection();
}
}catch(Exceptione){
e.printStackTrace();
}
returnconn;
}

//获得新连接
privatesynchronizedConnectionnewConnection()
throwsClassNotFoundException,SQLException{
Connectionconn=null;
if(dbBean!=null){
Class.forName(dbBean.getDriverName());
conn=DriverManager.getConnection(dbBean.getUrl(),
dbBean.getUserName(),dbBean.getPassword());
System.out.println("Info:获取新的连接.");
}
returnconn;
}

//释放连接
publicsynchronizedvoidreleaseConn(Connectionconn){
System.out.println("Info:当前链接是-->"+conn);
System.out.println("Info:活动的链接数量是-->"+activeConnection.size());
//如果链接没有关闭
if(isValid(conn)){
freeConnection.add(conn);
activeConnection.remove(conn);
threadLocal.remove();

}else{
System.out.println("Info:无法释放该链接。");
}
notifyAll(); //
需要唤醒等待。
}

//判断连接是否可用
privatebooleanisValid(Connectionconn){
try{
if(conn==null||conn.isClosed()){
returnfalse;
}
}catch(SQLExceptione){
e.printStackTrace();
}
returntrue;
}

//定时检查关闭未占用的链接。
publicsynchronizedvoiddestroyFreeAndMoveToOther(){
newTimer().schedule(newTimerTask(){
@Override
publicvoidrun(){
System.out.println("Info:----------------定时任务开始释放空闲连接,即移动到其他链接中----------------------");
for(inti=0;i<freeConnection.size();i++){
ConnectionfreeConn=freeConnection.get(i);
if(isValid(freeConn)){
otherConnection.add(freeConn);
freeConnection.remove(freeConn);
threadLocal.remove();
}
}
}
},dbBean.getReleaseConnTime(),dbBean.getReleaseConnTime());

}
//定时检查连接池情况
@Override
publicvoidcheackPool(){
if(dbBean.isCheckPool()){
newTimer().schedule(newTimerTask(){
@Override
publicvoidrun(){
IntegerfreeSize=freeConnection.size();
// 1.对线程里面的连接状态
if(activeConnection.size()==0&&freeSize>0){
System.out.println("Info:==========================定时任务开始关闭空闲连接=======================================");
try{
for(ConnectionfreeConn:freeConnection){

threadLocal.remove();
freeConn.close(); //
需要先从当前线程中移除conn后,再关闭链接。
}
freeConnection.clear();
}catch(Exceptione){
e.printStackTrace();
}
}
totalConn=freeConnection.size()+activeConnection.size()+otherConnection.size();
// 2.连接池最小最大连接数
System.out.println("Info:free连接数-->"+freeConnection.size());
System.out.println("Info:active连接数-->"+activeConnection.size());
System.out.println("Info:other连接数-->"+otherConnection.size());
System.out.println("Info:total连接数-->"+totalConn);

}
},dbBean.getLazyCheck(),dbBean.getPeriodCheck());
}
}
@Override
publicvoiddestroyLongTimeNotUseConn(){
newTimer().schedule(newTimerTask(){
@Override
publicvoidrun(){
try{
System.out.println("Info:--------------我们开始摧毁那些长时间不使用的空闲链接--------------------");
for(inti=0;i<freeConnection.size();i++){
ConnectionfreeConn=freeConnection.get(i);
if(isValid(freeConn)){
freeConnection.remove(freeConn);
threadLocal.remove();
System.out.println("Info:关闭的空闲链接是-->"+freeConn);
freeConn.close(); //
需要先从当前线程中移除conn后,再关闭链接。
}
}
System.out.println("Info:我们开始摧毁那些长时间不使用的其他链接。");
for(intj=0;j<otherConnection.size();j++){
ConnectionotherConn=otherConnection.get(j);
if(isValid(otherConn)){
otherConnection.remove(otherConn);
threadLocal.remove();
System.out.println("Info:关闭的其他链接是-->"+otherConn);
otherConn.close(); //
需要先从当前线程中移除conn后,再关闭链接。
}
}
}catch(ExceptiondestoryExp){
System.out.println("Error:销毁空闲链接和其他链接发生错误了-->"+destoryExp.toString());
}

//我们需要还原连接池的状态。
isActive=false;
totalConn=activeConnection.size();
}
},dbBean.getDestroyConnTime(),dbBean.getDestroyConnTime());
}

}
(4)配置文件加载类

packagecom.yjf.java.utils;

importcom.yjf.java.bean.DBInfo;

importjava.io.FileReader;
importjava.io.IOException;
importjava.util.Properties;

/**
* Created by rooton 20170924.
* Update date:
* <p>
* Time: 1:24 PM
* Project:test-java
* Package:com.yjf.java.utils
* Describe :
* <p>
* Result of Test:test ok,test error
* Command:
* <p>
* <p>
* Email: jifei.yang@ngaa.com.cn
* Status:Using online
* Attention:
*/
publicclassPropertiesHelpUtil{

privateStringproPath="/db/phoenix-pool.properties";

publicPropertiesHelpUtil(){}

privatesynchronizedPropertiesgetAllProp(Stringpath){
Propertiesproperties=newProperties();
try{
properties.load(PropertiesHelpUtil.class.getResourceAsStream(proPath));
returnproperties;
}catch(IOExceptionex){
System.err.println("Readproperties
error:"+ex.toString()+"....................................................");
}
returnnull;
}

publicsynchronizedDBInfoinitDb(){
Propertiesproperties=getAllProp(proPath);
Stringuser=properties.getProperty("username");
Stringpwd=properties.getProperty("password");
Stringurl=properties.getProperty("url");
StringdriverClassName=properties.getProperty("driverClassName");
StringpoolName=properties.getProperty("poolName");
IntegerinitConnections=Integer.parseInt(properties.getProperty("initConnections","2"));
IntegermaxActiveConnections=Integer.parseInt(properties.getProperty("maxActiveConnections","30"));
longconnectionTimeOut=Long.parseLong(properties.getProperty("connectionTimeOut","20000"));
booleanisCurrentConnection=Boolean.parseBoolean(properties.getProperty("isCurrentConnection","true"));
booleanisCheckPool=Boolean.parseBoolean(properties.getProperty("isCheckPool","true"));
longlazyCheck=Long.parseLong(properties.getProperty("lazyCheck","30000"));
longperiodCheck=Long.parseLong(properties.getProperty("periodCheck","30000"));
longreleaseConnTime=Long.parseLong(properties.getProperty("releaseConnTime","60000"));
longdestroyConnTime=Long.parseLong(properties.getProperty("destroyConnTime","600000"));

returnnewDBInfo(driverClassName,url,user,pwd,poolName,initConnections,maxActiveConnections
,connectionTimeOut,isCurrentConnection,isCheckPool,lazyCheck,
periodCheck,releaseConnTime,destroyConnTime);
}

}
(5)连接池管理类

packagecom.yjf.java.utils;
importcom.yjf.java.bean.DBInfo;
importcom.yjf.java.core.IConnectionPool;
importcom.yjf.java.core.IConnectionPoolImpl;

importjava.sql.Connection;

importjava.util.concurrent.ConcurrentHashMap;

/**
* Created by rooton 20170924.
* Update date:
* <p>
* Time: 2:37 PM
* Project:test-java
* Package:com.yjf.java.utils
* Describe :Connection pool management class.
* <p>
* Result of Test:test ok,test error
* Command:
* <p>
* <p>
* Email: jifei.yang@ngaa.com.cn
* Status:Using online
* Attention:
*/
publicclassDBFactoryManager{

// 连接池存放
privateConcurrentHashMap<String,IConnectionPool>pools=newConcurrentHashMap<>();

//初始化
privateDBFactoryManager(){
init();
}
//单例实现
publicstaticDBFactoryManagergetInstance(){
returnSingtonle.instance;
}
privatestaticclassSingtonle{
privatestaticDBFactoryManagerinstance= newDBFactoryManager();
}
//初始化所有的连接池
privatevoidinit(){
DBInfobean=newPropertiesHelpUtil().initDb();
IConnectionPoolImplpool=newIConnectionPoolImpl(bean);
pools.put(bean.getPoolName(),pool);
System.out.println("Info:成功初始化连接池-->"+bean.getPoolName());
}

//获得连接,根据连接池名字获得连接
publicConnection getConnection(StringpoolName){
Connectionconn=null;
if(pools.size()>0&&pools.containsKey(poolName)){
conn=getPool(poolName).getConnection();
}else{
System.err.println("Error:找不到这个连接池-->"+poolName);
}
returnconn;
}

//关闭,回收连接
publicvoidclose(StringpoolName,Connectionconn){
IConnectionPoolpool=getPool(poolName);
try{
if(pool!=null){
pool.releaseConn(conn);
}
}catch(Exceptione){
System.out.println("Error:连接池已被销毁。");
e.printStackTrace();
}
}

//获得连接池
publicIConnectionPoolgetPool(StringpoolName){
IConnectionPoolpool=null;
if(pools.size()>0){
pool=pools.get(poolName);
}
returnpool;
}
//清空连接池
publicvoiddestroy(StringpoolName){
IConnectionPoolpool=getPool(poolName);
if(pool!=null){
System.out.println("Info:清空连接池。");
pool.destroyFreeAndMoveToOther();
pool.isActive(false);
}
}

}

(6)配置文件

url=jdbc:mysql://192.168.1.1:3306/mysql?characterEncoding=GBK
driverClassName=com.mysql.jdbc.Driver
username=root
password=123123

# Pool name .
poolName=mysqlPool
# Initialize the number of database connections.
initConnections=2

# The maximum number of connections allowed iscorresponding to the settings of the database.
maxActiveConnections=5

# whether to get the current connection, default true.
isCurrentConnection=true
# Do you need to check the connection pool regularly?
isCheckPool=true

############################Atention :destroyConnTime> lazyCheck(periodCheck) > releaseConnTime>connectionTimeOut #######

# How long will it take to destroy a link?.
destroyConnTime=37000

# How long does it take to start checking? Check thefrequency of database links.
lazyCheck=12000
periodCheck=12000

# How many milliseconds release a free link?
releaseConnTime=10000

# Repeat the frequency of the connection (inmilliseconds).
connectionTimeOut=50000

(7)测试类

packagecom.test.java.Thread;

importcom.yjf.java.core.IConnectionPool;
importcom.yjf.java.utils.DBFactoryManager;

importjava.sql.Connection;
importjava.util.Timer;
importjava.util.TimerTask;

/**
* Created by rooton 20170924.
* Update date:
* <p>
* Time: 4:53 PM
* Project:test-java
* Package:com.test.java.Thread
* Describe :
* <p>
* Result of Test:test ok,test error
* Command:
* <p>
* <p>
* Email: jifei.yang@ngaa.com.cn
* Status:Using online
* Attention:
*/
publicclassTestConn{

privatestaticsynchronizedConnectiongetConn(DBFactoryManager mm){
returnmm.getConnection("mysqlPool");
}

publicstaticvoidmain(String[]args)throwsException{
Stringname="mysqlPool";
DBFactoryManagerdbFactoryManager=DBFactoryManager.getInstance();
IConnectionPool poll=dbFactoryManager.getPool(name);

Threadth0=newThread(newRunnable(){
@Override
publicvoidrun(){
for(inti=0;i<5;i++){
Connectioncd=getConn(dbFactoryManager);
System.out.println(i+"--th0-------->"+cd);
try{
Thread.sleep(10000);
dbFactoryManager.close(name,cd);
}catch(Exceptione){
e.printStackTrace();
}

}
}
});

Threadth1=newThread(newRunnable(){
@Override
publicvoidrun(){
for(inti=0;i<4;i++){
Connectionconn=getConn(dbFactoryManager);
System.out.println(i+"--th1-------->"+conn);
try{
Thread.sleep(10000);
dbFactoryManager.close(name,conn);
}catch(Exceptione){
e.printStackTrace();
}

}
}
});

Threadth2=newThread(newRunnable(){
@Override
publicvoidrun(){
for(inti=0;i<5;i++){
Connectioncn=getConn(dbFactoryManager);
System.out.println(i+"--th2-------->"+cn);
try{
Thread.sleep(10000);
poll.releaseConn(cn);
}catch(Exceptione){
e.printStackTrace();
}

}
}
});

Threadth3=newThread(newRunnable(){
@Override
publicvoidrun(){
for(inti=0;i<5;i++){
Connectionconn=getConn(dbFactoryManager);
System.out.println(i+"--th3-------->"+conn);
try{
Thread.sleep(9000);
dbFactoryManager.close(name,conn);
}catch(Exceptione){
e.printStackTrace();
}

}
}
});

Threadth4=newThread(newRunnable(){
@Override
publicvoidrun(){
for(inti=0;i<3;i++){
Connectionconn=getConn(dbFactoryManager);
System.out.println(i+"--th4-------->"+conn);
try{
Thread.sleep(12000);
dbFactoryManager.close(name,conn);
}catch(Exceptione){
e.printStackTrace();
}

}
}
});

th0.start();
th1.start();
th2.start();
th3.start();
th4.start();
newTimer().schedule(newTimerTask(){
@Override
publicvoidrun(){
for(inti=0;i<1;i++){
Connectionconn=getConn(dbFactoryManager);
System.out.println(i+"--schedule
01-------->"+conn);
try{
Thread.sleep(100);
dbFactoryManager.close(name,conn);
}catch(Exceptione){
e.printStackTrace();
}

}
}
},10000,10000);

newTimer().schedule(newTimerTask(){
@Override
publicvoidrun(){
for(inti=0;i<1;i++){
Connectionconn=getConn(dbFactoryManager);
System.out.println(i+"--schedule
02-------->"+conn);
try{
Thread.sleep(100);
dbFactoryManager.close(name,conn);
}catch(Exceptione){
e.printStackTrace();
}

}
}
},15000,15000);
}
}

2、阿里巴巴的druid连接池

(1)配置文件(参考配置)

driverClassName=org.apache.phoenix.jdbc.PhoenixDriver
minIdle=2
initialSize=2
#最大连接池数量
maxActive=200
#获取连接时最大等待时间
maxWait=15000
testOnBorrow=false
testOnReturn=false
#如果空闲时间大于timeBetweenEvictionRunsMillis,执行validationQuery检测连接是否有效
testWhileIdle=true
timeBetweenEvictionRunsMillis=400000
validationQuery=select 'x'
validationQueryTimeout=1000
initConnectionSqls=select 'x'

#对于建立时间超过removeAbandonedTimeout的连接强制关闭 (destory time is 5 seconds)
removeAbandoned=true
removeAbandonedTimeout=300


poolPreparedStatements=true
#配置一个连接在池中最小生存的时间,单位是毫秒
minEvictableIdleTimeMillis=300000

(2)德鲁伊连接池管理类

packagecom.ngaa.webservice.utils;

importcom.alibaba.druid.pool.DruidDataSource;
importcom.alibaba.druid.pool.DruidDataSourceFactory;
importcom.alibaba.druid.pool.DruidPooledConnection;
importjava.io.InputStream;
importjava.io.Serializable;
importjava.sql.Connection;
importjava.sql.PreparedStatement;
importjava.sql.ResultSet;
importjava.sql.SQLException;
importjava.util.Properties;
importjava.util.Timer;
importjava.util.TimerTask;

importcom.ngaa.webservice.bean.common.pool.DBInfo;
importcom.ngaa.webservice.bean.common.pool.GlobalPathBean;
importorg.slf4j.Logger;
importorg.slf4j.LoggerFactory;
/**
* Created by rooton 20171101.
* Update date:
* <p>
* Time: 4:22 PM
* Project:cdn-license-webservice
* Package:com.ngaa.webservice.utils
* Describe :
* <p>
* Result of Test:test ok,test error
* Command:
* <p>
* <p>
* Email: jifei.yang@ngaa.com.cn
* Status:Using online
* Attention:
*/

publicclassDBConnectionFactoryimplementsSerializable{
privatestaticLoggerlogger=LoggerFactory.getLogger(DBConnectionFactory.class);
privatestaticDBConnectionFactorydbConnectFactory=null;
privatestaticDruidDataSourcedataSource=null;
final staticDBInfodbInfo=newPropertiesHelpUtil().initDb();
publicDBConnectionFactory()
{
this.dataSource=initDataSource();
// this.closeAllConn();
}

publicstaticsynchronizedDBConnectionFactorygetDBConnectFactory()
{
logger.warn("connection;get
connect Factory...........................");

if(null==dbConnectFactory||dataSource.isClosed()){
dbConnectFactory=newDBConnectionFactory();
logger.warn("connectionis
null ; get connect Factory again...........................");

}
logger.warn("returnconnection
factory..................................");

returndbConnectFactory;
}

publicConnectiongetConnection()
{
DruidPooledConnectionconnection=null;
if(this.dataSource!=null){
try
{
logger.warn("connection;before
get the datasource .......................");

connection=this.dataSource.getConnection();
logger.warn("connection;dataSource
url:{}",connection.getMetaData().getURL());

}
catch(SQLExceptione)
{
thrownewRuntimeException(e);
}
}else{
logger.error("connection;data
source not init ..............................");

}
returnconnection;
}

publicvoiddestoryDataSource()
{
if(this.dataSource!=null)
{
this.dataSource.close();
logger.warn("connection;data
source pool is closed...........................");

}
else
{
logger.warn("connection;data
source is not init ,so can not close the pool...");

}
}

privateDruidDataSourceinitDataSource()
{
InputStreaminput=null;
try
{
logger.warn("Connection;start
load the file of properties......................");

PropertiesdbProp=newProperties();
input=getClass().getResourceAsStream(GlobalPathBean.PHOENIX_PROPERTIES_PATH);
dbProp.load(input);
Stringurl="jdbc:phoenix:"+dbInfo.getQuorum()+":/hbase:"+dbInfo.getUsername()+":"+dbInfo.getKeyPath();
logger.warn("url is{}",url);
dbProp.setProperty("url",url);
NgaaSafetyInitUtils.autherLogin(dbInfo.getQuorum(),dbInfo.getKrb5(),dbInfo.getUsername(),dbInfo.getKeyPath());
DruidDataSourcedruidDataSource=(DruidDataSource)DruidDataSourceFactory.createDataSource(dbProp);
logger.warn("connection;the
time of max waittime{}............................",druidDataSource.getMaxWait());

logger.warn("connection;the
number of max connection {} ........................",druidDataSource.getMaxActive());

returndruidDataSource;
}
catch(Exceptionex)
{
logger.error("connection;load
the file of properties is error,and create the data pollerror......................");

thrownewRuntimeException(ex);
}
}

publicstaticvoidreleaseConn(PreparedStatementpstm,ResultSetrs,Connectionconn)
throwsSQLException
{
if(rs!=null){
rs.close();
}
if(pstm!=null){
pstm.close();
}
if(conn!=null){
conn.close();
}
}

}

(3)测试获取链接和释放链接

// Get connection

Connection connect =DBConnectionFactory.getDBConnectFactory().getConnection();

System.out.println(connect);

try {

// Release connection.

DBConnectionFactory.releaseConn(null, null,connect);

} catch (SQLException e) {

e.printStackTrace();

}

应用场景是什么?

连接池特别适用于在连接请求被丢弃或延迟的高负载环境中优化性能。这种情况对应用程序的整体性能有不利的影响。实际上,在创建JDBC Web或企业应用程序时,出于所有实际的原因始终使用连接池。第三方库非常稳定,能够提供他们稳定的东西,理解连接池的概念并能够实现它们是所有JDBC程序员必须的,但是不推荐使用自己定义的连接池,只能自己玩着测试使用,不可生产环境上应用。。。



参考

(1)德鲁伊官方:https://github.com/alibaba/druid

(2)博客:

http://www.snaq.net/java/DBPool/

https://www.developer.com/java/data/understanding-jdbc-connection-pooling.html

http://greemranqq.iteye.com/blog/1969273

感谢以下两位的支持:

http://my.csdn.net/gogogogood

http://my.csdn.net/Sosog_Jung
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: