?? 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 + -