package chars.pool;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import COM.ibm.db2.jdbc.app.DB2Driver;
/**
* JDK version used : jdk1.4.2_07 <br>
* Description : 一个数据库连接池的实现 <br>
* Comments Name : CharsConnectionPool <br>
* author :chars <br>
* date :2007-06-11<br>
* Version : 1.00 <br>
*/
public class CharsConnectionPool
{
//---------------连接数据库所需要的元素---------------
private String driver;
private String url;
private String userName;
private String password;
//----------------------------------------------
private List connections = null;//连接池的容器
private int intiateCount = 10;// 初始化连接数
private int maxCount = 100;// 连接池可以产生的最大连接数
private int rateCount = 10;// 连接不够时一次可以申请的连接数
public static int ACTIVE_ACOUNT = 0;//记录目前的活动连接数
public String getDriver()
{
return driver;
}
public void setDriver(String driver)
{
this.driver = driver;
}
public int getIntiateCount()
{
return intiateCount;
}
public void setIntiateCount(int intiateCount)
{
this.intiateCount = intiateCount;
}
public int getMaxCount()
{
return maxCount;
}
public void setMaxCount(int maxCount)
{
this.maxCount = maxCount;
}
public String getPassword()
{
return password;
}
public void setPassword(String password)
{
this.password = password;
}
public int getRateCount()
{
return rateCount;
}
public void setRateCount(int rateCount)
{
this.rateCount = rateCount;
}
public String getUrl()
{
return url;
}
public void setUrl(String url)
{
this.url = url;
}
public String getUserName()
{
return userName;
}
public void setUserName(String userName)
{
this.userName = userName;
}
/**
* 连接池构造函数
* @param driver
* @param url
* @param userName
* @param password
* @param connections
*/
public CharsConnectionPool(String driver, String url, String userName, String password)
{
super();
this.driver = driver;
this.url = url;
this.userName = userName;
this.password = password;
}
public CharsConnectionPool(Properties p)
{
super();
this.driver = p.getProperty("driver");
this.url = p.getProperty("url");
this.userName = p.getProperty("userName");
this.password = p.getProperty("password");
}
/**
* 初始化连接池
*
*/
public void initiatePools()throws Exception
{
if (connections != null)return;//如果连接池已经建立则不再次进行初始化
connections = new ArrayList();
initParamters();//根据数据库支持的最大连接数配置该连接池的相关参数.
for (int i = 0; i < intiateCount; i++){
connections.add(newCharsConnection());
}
}
/**
* 销毁连接池
* @throws Exception
*/
public void destoryPools()throws Exception
{
if (connections == null) return ;
for(int i=0; i<connections.size();i++){
CharsPoolConnection conn = (CharsPoolConnection)connections.get(i);
if(conn.isBusy()) Thread.sleep(5000);//如果该连接正在使用则再给5秒时间
closeConnection(conn.getConnection());
connections.remove(conn);
}
connections = null;
}
/**
* 从连接池获取连接
*
*/
public Connection getConnection()throws SQLException
{
Connection conn = null;
try{
conn = getFreeConnection();
if(conn == null) {
Thread.sleep(3000);//暂停3秒钟再试着获取连接
conn = getFreeConnection();
}
if(conn == null) {//此时如果还不能获得连接则表示,连接池中的连接已经用完
throw new SQLException("连接池连接连接使用枯竭,请稍后再试!!");
}
}catch(Exception e)
{
e.printStackTrace();
}
return conn;
}
/**
* 归还连接到连接池(当连接用完时)
* @param conn
*/
public void rebackConnection(Connection conn)
{
for(int i = 0;i < connections.size();i++){
CharsPoolConnection charsCon = (CharsPoolConnection)connections.get(i);
if(charsCon.getConnection() == conn){
charsCon.setBusy(false);
conn = null;//外部引用为空.
ACTIVE_ACOUNT --;
break;
}
}
}
// ---------------------------------------------------------------------------------------------------
/**
* 加载驱动程序,配置实际上可以用的最大连接数
*/
private void initParamters() throws Exception
{
int realMaxCount = -1;
Connection con = null;
try
{
Driver driver1 = new DB2Driver();
DriverManager.registerDriver(driver1);
con = DriverManager.getConnection(this.url, this.userName, this.password);
DatabaseMetaData dmd = con.getMetaData();
realMaxCount = dmd.getMaxConnections();
if(realMaxCount == 0){//如果返回的值为0,则表示最大的连接数不受限制
realMaxCount = 1000;//那么默认赋一个较大的值给它
}
}
finally{
if(con == null) con.close();
}
if(realMaxCount < intiateCount) {//如果数据库允许的最大活动连接数小于初始化的连接数
intiateCount = maxCount; //则实际上初始化的连接数应该等于数据库允许的最大活动连接数据
maxCount = realMaxCount;
}
else if(intiateCount < realMaxCount && maxCount >= realMaxCount){//如果数据库最大的活动连接数大于初始化连接数但是小于该连接池允许的最大连接数
maxCount = realMaxCount; //则该池的最大连接数等于数据库允许的最大活动连接数
}
}
/**
* 获取可以用的连接,如果没有查找到则根据条件在池中加入新的连接
* @return
* @throws SQLException
*/
private Connection getFreeConnection()throws SQLException
{
Connection conn = null;
conn = findFreeConnection();//首先到连接池中找空闲的连接
if(conn == null){//如果没有找到,则试着产生新的连接放入池中
for(int i = 1; connections.size() < maxCount && i <= rateCount;i++){//是否再能在连接池中增加连接取决与maxCount
connections.add(newCharsConnection());
}
conn = findFreeConnection();//再次在连接池中找
}
return conn;
}
/**
* 在池中查找可以使用的连接
* @return
*/
private Connection findFreeConnection()throws SQLException
{
CharsPoolConnection charsConn = null;
Connection conn = null;
for(int i = 0; i < connections.size();i++){
charsConn = (CharsPoolConnection)connections.get(i);
if(charsConn.isBusy())continue;
else {
if(!isAvalidConnection(charsConn.getConnection())) {
charsConn.setConnection(newConnection());
}
conn = charsConn.getConnection();//得到可以用的连接
charsConn.setBusy(true);//表明为使用状态
ACTIVE_ACOUNT++;
break;
}
}
return conn;
}
/**
* 判断池中的连接是否因为其他原因变得不可以用
* @param conn
* @return
*/
private boolean isAvalidConnection(Connection conn)
{
try
{
conn.setAutoCommit(true);//模拟动作,如果能够能够操作则说明该连接可用
}catch(SQLException e)
{
closeConnection(conn);
return false;
}
return true;
}
/**
* 判断一个连接是否还可以用,如果不可以用则创建一个新的连接代替它
* @param conn
* @return
*/
private CharsPoolConnection newCharsConnection()throws SQLException
{
CharsPoolConnection charsCon = new CharsPoolConnection();
charsCon.setConnection(newConnection());
charsCon.setBusy(false);
return charsCon;
}
/**
* 获取一个新的数据库连接
* @return
* @throws SQLException
*/
private Connection newConnection()throws SQLException
{
return DriverManager.getConnection(this.url,this.userName,this.password);
}
/**
* 关闭数据库连接
* @param conn
*/
private void closeConnection(Connection conn)
{
try
{
conn.close();
}catch(SQLException se)
{
System.out.println("关闭连接发生异常...");
}
}
}
封装连接池的连接:
package chars.pool;
public class CharsPoolConnection
{
private boolean isBusy;
private java.sql.Connection connection;
public java.sql.Connection getConnection()
{
return connection;
}
public void setConnection(java.sql.Connection connection)
{
this.connection = connection;
}
public boolean isBusy()
{
return isBusy;
}
public void setBusy(boolean isBusy)
{
this.isBusy = isBusy;
}
}
调用的方式大致可以这样:
CharsConnectionPool pool = new CharsConnectionPool(env);
pool.initiatePools();
Connection conn= pool.getConnection(); //获取连接
//do something with your code;
pool .rebackConnection(conn); 归还连接到连接池