📄 connectionpool.java
字号:
package com.ywh.dbcp;
/**
* <p>Title: greatom toolkit</p>
* <p>Description: db util</p>
* <p>Copyright: Copyright (c) 2002</p>
* <p>Company: 北京长通联合宽带网络技术有限公司</p>
* @author zhengzp
* @version 1.0
*/
/**
* add a comment test the notify function.
* **/
import java.io.*;
import java.sql.*;
import java.util.*;
import org.apache.log4j.*;
/**
* 封装数据库连接,实现连接池。<br>
*ConnectionPool在内部维护激活连接和未激活连接两个链表,客户申请一个连接时,从未激活连接中找到一个连接,
*返回给客户,并把这个连接加入到激活连接中。用户关闭连接时,做相反的操作。
*同时,ConnectionPool使用一个后台进程定时扫描激活连接,看是否激活的时间过长了。如果是,说明程序中没有释放,
*ConnectionPool做一个记录,并关闭此连接。
*后台进程还要扫描未激活连接,执行一个简单的sql查询,如在oracle中可以执行"select * from dual;",以确保连接不会因为超时
*而断开,一旦连接断开,后台进程会重新建立连接。
* @author zhengzp
* @version 1.0
*@see java.sql.Connection
*/
public class ConnectionPool implements Serializable, IConnectionPool{
private class ScanTask extends Thread{
/**连接池的自动维护线程,这个线程要做两个操作:<br>
*1、扫描激活的连接,如果连接时间过长,则认为程序没有释放,记录下错误,并释放连接。<br>
*2、扫描未激活的连接,如果空闲时间过长,则做一次测试,即做一次简单查询,以保证连接可用。
* 如果连接不可用,则重新生成连接。
* */
public void run(){
while (!_runner.isInterrupted()) {
synchronized (this) {
////log the autoscan
cat.debug("ConnectionPool AutoScan start");
//log.debug("ConnectionPool AutoScan start");
long now = System.currentTimeMillis();
ConnectionWrap cw;
ListIterator iterator = _activeConnList.listIterator();
while (iterator.hasNext()) {
cw = (ConnectionWrap) iterator.next();
if (now - cw.getDate().getTime() > overdurPeriod) {
////log the error
cat.warn("ConnectionPool auto scan found a overdue active connection, the connection owner Class is " +
cw.getOwnerClassName());
cat.warn("");
//如果一个活动的连接超时,就把他从活动链表中删除,并关闭这个连接
iterator.remove();
--_activeConnCount;
try {
--_poolSize;
cw.conn.close();
}
catch (SQLException e) { /*do nothing*/}
} //if
} //while
iterator = _inactiveConnList.listIterator();
while (iterator.hasNext()) {
cw = (ConnectionWrap) iterator.next();
if (now - cw.getDate().getTime() > testPeriod) {
try {
cat.debug("ConnectionPool autoscan test a connection..");
//log.debug("ConnectionPool autoscan test a connection..");
Statement stat = cw.createStatement();
stat.execute(testCommand);
stat.close();
cw.setDate();
cat.debug("ConnectionPool autoscan test a connection OK..");
//log.debug("ConnectionPool autoscan test a connection OK..");
}
catch (SQLException e) {
////log the error
cat.error(
"ConnectionPool auto scan test Inactive connection Error:",
e);
//log.error("ConnectionPool auto scan test Inactive connection Error:",e);
try {
--_poolSize;
iterator.remove();
cw.conn.close();
}
catch (SQLException e1) { /*do nothing*/}
try {
iterator.add(createConnection());
++_poolSize;
}
catch (SQLException e1) { /*do nothing*/}
} //try
} //if
} //while
//如果pool中的数量少于初始化的数量。在free中增加。
while (_poolSize < initPoolSize) {
try {
_inactiveConnList.addLast(createConnection());
++_poolSize;
}
catch (SQLException e1) { /*do nothing*/}
}
//如果pool中的数量太多,应该关闭一些。
while ( (_poolSize - _activeConnCount) > initPoolSize) {
try {
cw = (ConnectionWrap) _inactiveConnList.removeLast();
cw.conn.close();
--_poolSize;
}
catch (SQLException e1) {
cat.error("close inactive connection error", e1);
}
}
} //synchronized
////log the autoscan
cat.debug("ConnectionPool AutoScan end");
//log.debug("ConnectionPool AutoScan end");
try {
_runner.sleep(scanPeriod); //等待扫描时间,或被close方法触发
}
catch (InterruptedException e) {
break;
}
} //while
}
}
// public ini
private static Logger cat = Logger.getLogger(ConnectionPool.class);
private ScanTask _runner; //后台的自动维护线程
private LinkedList _activeConnList; //活动连接链表
private LinkedList _inactiveConnList; //空闲连接链表
private int _poolSize; //连接池大小
private int _activeConnCount; //活动连续数
private DBInfo dbInfo;
/* the period the scaner run once,default is 10 minute*/
private long scanPeriod=1000*60*10L;//1000*60*30l;
/* the period we think the active connection is overdue, default is 5 minute */
private long overdurPeriod=1000*60*5L;//1000*60*60l;
/* the period the scaner should do a test to check inactive connection*/
private long testPeriod = scanPeriod;
/* the SQL command the test should excute */
private String testCommand="select * from t_cms_tree";
private int maxPoolSize; //连接池的最大容量
private int initPoolSize; //连接池的初始大小
/**一个静态的连接池。
* */
// private static ConnectionPool pool;
/**初始化缺省连接池。
* @param config 连接池的配置,必需是xml格式
* @return 如果成功,将静态连接池初始化,返回true,否则返回false
* *//*
public static boolean initial(Element config)
{
boolean result = false;
DBInfo dbInfo = new DBInfo(config.getChild("database"));
ConnectionPoolInfo poolInfo = new ConnectionPoolInfo(config);
try
{
pool = new ConnectionPool(dbInfo, poolInfo);
result = true;
}catch(Exception e)
{
e.printStackTrace();
}
return result;
}*/
/**初始化缺省连接池。
* @param fileName 一个xml格式的文件。
* @see #initial(Element config)
* @return 如果成功,将静态连接池初始化,返回true,否则返回false。
* *//*
public static boolean initial(String fileName)
{
boolean result = false;
if ( pool != null )
{
pool.close();
}
try{
InputStream in = new BufferedInputStream(new FileInputStream(fileName));
SAXBuilder builder = new SAXBuilder();
Document configDoc = builder.build(in);
Element rootConfig = configDoc.getRootElement();
result = initial(rootConfig);
}catch(Exception t){
t.printStackTrace();
}
return result;
}*/
/**得到一个静态连接池,全局实例
* 可以在不同类之间共享连接池。
* @return 得到一个静态连接池。
*
public static ConnectionPool getPool()
{
return pool;
}*/
public ConnectionPool(){}
/**根据给定的连接池参数,创建一个新的连接。
* @return 根据给定的连接池参数,创建一个新的连接*/
private ConnectionWrap createConnection() throws SQLException{
ConnectionWrap cw;
try {
cw=new ConnectionWrap(this, dbInfo.getConnection());
cw.setDate();
}
catch (SQLException e){
//log the error
//log.error(e);
cat.error("create connection error", e);
throw e;
}
return (cw);
}
/**得到连接池的初始容量。
* @return 得到连接池的初始容量。
* */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -