这是我参考一些例子写的一个pool。里面有些系统相关的东西,所以不能直接用。不过我希望大家能了解到他的原理,所以也就没去掉。
另外,这个类写的较早,也没有按规范写javadoc。但是注释改写的基本写全了。大家发布的时候,自己转换一下吧。

package com.yup.lib.dataaccess;
import java.sql.*;
import java.util.*;
import com.yup.lib.*;
import com.yup.lib.debug.*;
/**
* <p>Title: </p>
* <p>Description: </p>
* <p>Copyright: Copyright (c) 2001</p>
* <p>Company: YupStudio.</p>
* @author Miles.Chang
* @version 1.00
*/
public class ConnectionPool implements Runnable {
// instead of util.ArrayList, we use Vector because it is synchronized.
private Vector availableConnections, busyConnections;
// a flag.
private boolean connectionPending = false;
// a counter for fatigue connection releasing.
private int freeTimes = 0;
// default configuration of the pool.
private final static int DEF_REUSE_UP_LIMIT = 500;
private final static int DEF_INIT_CONNECTIONS = 1;
private final static int DEF_MAX_CONNECTIONS = 5;
private final static boolean DEF_WAIT_IF_BUSY = true;
// variables for establishing the connection.
private String driver;
private String url;
private String username;
private String password;
// pool configuration variables.
private int initConnections;
private int reuseUpLimit;
private int maxConnections;
private boolean waitIfBusy;
// the driver.
private Driver drvDriver;
// exception descriptions.
private static final String EX_INVALID_INIT_PARAM = "invalid initialzing parameter.";
private final static String EX_LIMIT_REACHED = "Connection limit reached";
private final static String EX_DRIVER_NOT_FOUND = "Can't find class for driver: ";
private final static String EX_POOL_NOT_INIT = "Connection pool has not been initialized.";
private final static String EX_POOL_HAS_INIT = "Connection pool has been initialized. You should close it up at first.";
// singleton pattern.
private ConnectionPool(String driver, String url,
String username, String password,
int initConnections, int reuseUpLimit,
int maxConnections, boolean waitIfBusy)
throws SQLException {
// NumberKit nk = NumberKit.getInstance();
//
// try {
// driver = Const.readSetting("com.yup.lib.dataaccess.ConnectionPool.driver");
// url = Const.readSetting("com.yup.lib.dataaccess.ConnectionPool.url");
// username = Const.readSetting("com.yup.lib.dataaccess.ConnectionPool.username");
// password = Const.readSetting("com.yup.lib.dataaccess.ConnectionPool.password");
// } catch(MissingResourceException ex) {
// throw new MissingResourceException("com.yup.lib.dataaccess.ConnectionPool(): " + ex.getMessage(), ex.getClassName(), ex.getKey());
// }
//
// try {
// initConnections = nk.getInt(Const.readSetting("com.yup.lib.dataaccess.ConnectionPool.initConnections"));
// } catch(MissingResourceException ex) {
// initConnections = DEF_INIT_CONNECTIONS;
// }
//
// try {
// reuseUpLimit = nk.getInt(Const.readSetting("com.yup.lib.dataaccess.ConnectionPool.reuseUpLimit"));
// } catch(MissingResourceException ex) {
// reuseUpLimit = DEF_REUSE_UP_LIMIT;
// }
//
// try {
// maxConnections = nk.getInt(Const.readSetting("com.yup.lib.dataaccess.ConnectionPool.maxConnections"));
// } catch(MissingResourceException ex) {
// maxConnections = DEF_MAX_CONNECTIONS;
// }
//
// try {
// waitIfBusy = Const.readSetting("com.yup.lib.dataaccess.ConnectionPool.waitIfBusy").trim().equalsIgnoreCase("TRUE");
// } catch(MissingResourceException ex) {
// waitIfBusy = DEF_WAIT_IF_BUSY;
// }
if(availableConnections!=null&&availableConnections.size()>0) {
throw new SQLException("com.yup.lib.dataaccess.ConnectionPool(): " + EX_POOL_HAS_INIT);
}
this.driver = driver;
this.url = url;
this.username = username;
this.password = password;
this.initConnections = initConnections<0?DEF_INIT_CONNECTIONS:initConnections;
this.reuseUpLimit = reuseUpLimit<1?DEF_REUSE_UP_LIMIT:reuseUpLimit;
this.maxConnections = maxConnections<1?DEF_MAX_CONNECTIONS:maxConnections;
this.waitIfBusy = waitIfBusy;
if(this.initConnections>this.maxConnections) {
throw new IllegalArgumentException("com.yup.lib.dataaccess.ConnectionPool(): " + EX_INVALID_INIT_PARAM);
}
loadDriver();
availableConnections = new Vector(this.initConnections);
busyConnections = new Vector();
for (int i=0;i<this.initConnections;i++) {
availableConnections.addElement(makeNewConnection());
}
}
// for singleton pattern.
private static Object initLock = new Object();
private static ConnectionPool pool;
// a typical double-checked locking block. HERE'S A TRAP!!
public static ConnectionPool getInstance()
throws SQLException {
if(pool==null) {
throw new SQLException("com.yup.lib.dataaccess.getInstance(): " + EX_POOL_NOT_INIT);
}
return pool;
}
// pool initializtion. this method should be called before using the pool.
public static void init(String driver, String url,
String username, String password,
int initConnections, int reuseUpLimit,
int maxConnections, boolean waitIfBusy)
throws SQLException {
if(pool==null) {
synchronized(initLock) {
if(pool==null) pool = new ConnectionPool(driver, url, username, password, initConnections, reuseUpLimit, maxConnections, waitIfBusy);
}
}
}
// get a connection.
public synchronized Connection getActiveConnection()
throws SQLException {
if (!availableConnections.isEmpty()) {
Connection existingConnection = (Connection)availableConnections.lastElement();
int lastIndex = availableConnections.size()-1;
availableConnections.removeElementAt(lastIndex);
// If connection on available list is closed (e.g.,it timed out), then
// remove it from available list and repeat the process of obtaining a
// connection.Also wake up threads that were waiting for a connection
// because maxConnection limit was reached.
if (existingConnection.isClosed()) {
Logger.debug("Exist connection closed, notify all and get a new free connection.");
notifyAll(); // Freed up a spot for anybody waiting
return(getActiveConnection());
} else {
busyConnections.addElement(existingConnection);
// debug when connection get.
Logger.debug("Get connection successfully!");
Logger.debug("Total connection: ");
Logger.debug(""+this.totalConnections());
Logger.debug("Available connections: ");
Logger.debug(""+availableConnections.size());
Logger.debug("Busy connections: ");
Logger.debug(""+busyConnections.size());
Logger.debug("");
return(existingConnection);
}
} else {
// Three possible cases:
// 1) You haven't reached maxConnections limit. So
// establish one in the background if there isn't
// already one pending, then wait for
// the next available connection (whether or not
// it was the newly established one).
// 2) You reached maxConnections limit and waitIfBusy
// flag is false. Throw SQLException in such a case.
// 3) You reached maxConnections limit and waitIfBusy
// flag is true. Then do the same thing as in second
// part of step 1: wait for next available connection.
if ((totalConnections()<maxConnections)&&!connectionPending) {
makeBackgroundConnection();
} else if (!waitIfBusy) {
throw new SQLException("com.yup.lib.dataaccess.ConnectionPool.getActiveConnection(): "+EX_LIMIT_REACHED);
}
// Wait for either a new connection to be established
// (if you called makeBackgroundConnection) or for
// an existing connection to be freed up.
try {
Logger.debug("No Availible Connection, Waiting...");
wait();
} catch(InterruptedException ie) {}
// Someone freed up a connection, so try again.
return(getActiveConnection());
}
}
// You can't just make a new connection in the foreground
// when none are available, since this can take several
// seconds with a slow network connection. Instead,
// start a thread that establishes a new connection,
// then wait. You get woken up either when the new connection
// is established or if someone finishes with an existing
// connection.
private void makeBackgroundConnection() {
connectionPending = true;
try {
Thread connectThread = new Thread(this);
connectThread.start();
} catch(OutOfMemoryError ex) {
Logger.debug("com.yup.lib.dataaccess.ConnectionPool.makeBackgroundConnection(): Out of memory error:" + ex.toString());
// Give up on new connection
}
}
// start a thread.
public void run() {
try {
Connection connection = makeNewConnection();
synchronized(this) {
availableConnections.addElement(connection);
connectionPending = false;
notifyAll();
}
} catch(Exception ex) { // SQLException or OutOfMemory
// Give up on new connection and wait for existing one
// to free up.
Logger.debug("com.yup.lib.dataaccess.ConnectionPool.run(): " + ex.toString());
}
}
// This explicitly makes a new connection. Called in
// the foreground when initializing the ConnectionPool,
// and called in the background when running.
private Connection makeNewConnection()
throws SQLException {
// Establish network connection to database
Connection connection = DriverManager.getConnection(url, username, password);
Logger.debug("Make new connection successfully!");
return(connection);
}
// Driver loading.
private void loadDriver()
throws SQLException {
try {
// Load database driver if not already loaded
drvDriver = (Driver)Class.forName(driver).newInstance();
DriverManager.registerDriver(drvDriver);
Logger.debug("Load driver succcessfully!");
} catch(ClassNotFoundException ex) {
// Simplify try/catch blocks of people using this by
// throwing only one exception type.
throw new SQLException("com.yup.lib.dataaccess.ConnectionPool.makeNewConnection():" + EX_DRIVER_NOT_FOUND + driver);
} catch(IllegalAccessException ex) {
// Simplify try/catch blocks of people using this by
// throwing only one exception type.
throw new SQLException("com.yup.lib.dataaccess.ConnectionPool.makeNewConnection():" + ex.getMessage());
} catch(InstantiationException ex) {
// Simplify try/catch blocks of people using this by
// throwing only one exception type.
throw new SQLException("com.yup.lib.dataaccess.ConnectionPool.makeNewConnection():" + ex.getMessage());
}
}
// Driver releasing.
private void releaseDriver()
throws SQLException {
DriverManager.deregisterDriver(drvDriver);
Logger.debug("Release driver succcessfully!");
}
// Free up a connection.
public synchronized void freeConnection(Connection connection) {
busyConnections.removeElement(connection);
availableConnections.insertElementAt(connection,0);
// Wake up threads that are waiting for a connection
Logger.debug("Free connection successfully, notifying...");
Logger.debug("Total connection: ");
Logger.debug(""+totalConnections());
Logger.debug("Available connections: ");
Logger.debug(""+availableConnections.size());
Logger.debug("Busy connections: ");
Logger.debug(""+busyConnections.size());
// reach up limit.release.
if(++freeTimes>reuseUpLimit) {
freeTimes = 0;
Logger.debug("================ Time to close some fatigued connections ===============");
try {
connection.close();
} catch (SQLException ex) {
Logger.debug("com.yup.lib.dataaccess.ConnectionPool.freeConnection(): " + ex.toString());
}
}
// Available Connection
Logger.debug("======================");
Logger.debug("========== " + (reuseUpLimit-freeTimes) + " ========");
Logger.debug("======================");
notifyAll();
}
// Get the count of current connections.
public synchronized int totalConnections() {
int intTotal = availableConnections.size() + busyConnections.size();
return intTotal;
}
/** Close all the connections. Use with caution:
* be sure no connections are in use before
* calling. Note that you are not <I>required</I> to
* call this when done with a ConnectionPool, since
* connections are guaranteed to be closed when
* garbage collected. But this method gives more control
* regarding when the connections are closed.
*/
private synchronized void closeAllConnections() {
this.closeConnections(availableConnections);
availableConnections = new Vector();
this.closeConnections(busyConnections);
busyConnections = new Vector();
}
// Destroy the pool.
public static void destory()
throws SQLException {
if(pool==null) {
throw new SQLException("com.yup.lib.dataaccess.destory(): " + EX_POOL_NOT_INIT);
}
pool.closeAllConnections();
pool.availableConnections = null;
pool.busyConnections = null;
pool.releaseDriver();
pool = null;
}
// Close up all the connections.
private void closeConnections(Vector connections) {
try {
for (int i=0; i<connections.size(); i++) {
Connection connection = (Connection)connections.elementAt(i);
if ( !connection.isClosed() ) {
Logger.debug("Connection closed succcessfully!");
connection.close();
}
}
} catch(SQLException ex) {
Logger.debug("com.yup.lib.dataaccess.ConnectionPool.freeConnection(): " + ex.toString());
// Ignore errors; garbage collect anyhow
}
}
// Get info.
public String toString() {
String info =
"ConnectionPool(" + url + "," + username + ")" +
", available=" + availableConnections.size() +
", busy=" + busyConnections.size() +
", max=" + maxConnections;
return(info);
}
// a test method.
public static void main(String[] args) {
try {
String url="jdbc:odbc:Driver=Microsoft Access Driver (*.mdb);DBQ=D:\\__!!MILES!!__\\dev\\jdbc\\xxx.mdb";
String driver = "sun.jdbc.odbc.JdbcOdbcDriver";
Global.initDBPool(driver, url);
} catch(Exception ex) {
ex.printStackTrace();
} finally {
try{
Global.destoryDBPool();
} catch(SQLException ex) {
ex.printStackTrace();
}
}
}
}
import java.sql.*;
import java.util.*;
import com.yup.lib.*;
import com.yup.lib.debug.*;
/**
* <p>Title: </p>
* <p>Description: </p>
* <p>Copyright: Copyright (c) 2001</p>
* <p>Company: YupStudio.</p>
* @author Miles.Chang
* @version 1.00
*/
public class ConnectionPool implements Runnable {
// instead of util.ArrayList, we use Vector because it is synchronized.
private Vector availableConnections, busyConnections;
// a flag.
private boolean connectionPending = false;
// a counter for fatigue connection releasing.
private int freeTimes = 0;
// default configuration of the pool.
private final static int DEF_REUSE_UP_LIMIT = 500;
private final static int DEF_INIT_CONNECTIONS = 1;
private final static int DEF_MAX_CONNECTIONS = 5;
private final static boolean DEF_WAIT_IF_BUSY = true;
// variables for establishing the connection.
private String driver;
private String url;
private String username;
private String password;
// pool configuration variables.
private int initConnections;
private int reuseUpLimit;
private int maxConnections;
private boolean waitIfBusy;
// the driver.
private Driver drvDriver;
// exception descriptions.
private static final String EX_INVALID_INIT_PARAM = "invalid initialzing parameter.";
private final static String EX_LIMIT_REACHED = "Connection limit reached";
private final static String EX_DRIVER_NOT_FOUND = "Can't find class for driver: ";
private final static String EX_POOL_NOT_INIT = "Connection pool has not been initialized.";
private final static String EX_POOL_HAS_INIT = "Connection pool has been initialized. You should close it up at first.";
// singleton pattern.
private ConnectionPool(String driver, String url,
String username, String password,
int initConnections, int reuseUpLimit,
int maxConnections, boolean waitIfBusy)
throws SQLException {
// NumberKit nk = NumberKit.getInstance();
//
// try {
// driver = Const.readSetting("com.yup.lib.dataaccess.ConnectionPool.driver");
// url = Const.readSetting("com.yup.lib.dataaccess.ConnectionPool.url");
// username = Const.readSetting("com.yup.lib.dataaccess.ConnectionPool.username");
// password = Const.readSetting("com.yup.lib.dataaccess.ConnectionPool.password");
// } catch(MissingResourceException ex) {
// throw new MissingResourceException("com.yup.lib.dataaccess.ConnectionPool(): " + ex.getMessage(), ex.getClassName(), ex.getKey());
// }
//
// try {
// initConnections = nk.getInt(Const.readSetting("com.yup.lib.dataaccess.ConnectionPool.initConnections"));
// } catch(MissingResourceException ex) {
// initConnections = DEF_INIT_CONNECTIONS;
// }
//
// try {
// reuseUpLimit = nk.getInt(Const.readSetting("com.yup.lib.dataaccess.ConnectionPool.reuseUpLimit"));
// } catch(MissingResourceException ex) {
// reuseUpLimit = DEF_REUSE_UP_LIMIT;
// }
//
// try {
// maxConnections = nk.getInt(Const.readSetting("com.yup.lib.dataaccess.ConnectionPool.maxConnections"));
// } catch(MissingResourceException ex) {
// maxConnections = DEF_MAX_CONNECTIONS;
// }
//
// try {
// waitIfBusy = Const.readSetting("com.yup.lib.dataaccess.ConnectionPool.waitIfBusy").trim().equalsIgnoreCase("TRUE");
// } catch(MissingResourceException ex) {
// waitIfBusy = DEF_WAIT_IF_BUSY;
// }
if(availableConnections!=null&&availableConnections.size()>0) {
throw new SQLException("com.yup.lib.dataaccess.ConnectionPool(): " + EX_POOL_HAS_INIT);
}
this.driver = driver;
this.url = url;
this.username = username;
this.password = password;
this.initConnections = initConnections<0?DEF_INIT_CONNECTIONS:initConnections;
this.reuseUpLimit = reuseUpLimit<1?DEF_REUSE_UP_LIMIT:reuseUpLimit;
this.maxConnections = maxConnections<1?DEF_MAX_CONNECTIONS:maxConnections;
this.waitIfBusy = waitIfBusy;
if(this.initConnections>this.maxConnections) {
throw new IllegalArgumentException("com.yup.lib.dataaccess.ConnectionPool(): " + EX_INVALID_INIT_PARAM);
}
loadDriver();
availableConnections = new Vector(this.initConnections);
busyConnections = new Vector();
for (int i=0;i<this.initConnections;i++) {
availableConnections.addElement(makeNewConnection());
}
}
// for singleton pattern.
private static Object initLock = new Object();
private static ConnectionPool pool;
// a typical double-checked locking block. HERE'S A TRAP!!
public static ConnectionPool getInstance()
throws SQLException {
if(pool==null) {
throw new SQLException("com.yup.lib.dataaccess.getInstance(): " + EX_POOL_NOT_INIT);
}
return pool;
}
// pool initializtion. this method should be called before using the pool.
public static void init(String driver, String url,
String username, String password,
int initConnections, int reuseUpLimit,
int maxConnections, boolean waitIfBusy)
throws SQLException {
if(pool==null) {
synchronized(initLock) {
if(pool==null) pool = new ConnectionPool(driver, url, username, password, initConnections, reuseUpLimit, maxConnections, waitIfBusy);
}
}
}
// get a connection.
public synchronized Connection getActiveConnection()
throws SQLException {
if (!availableConnections.isEmpty()) {
Connection existingConnection = (Connection)availableConnections.lastElement();
int lastIndex = availableConnections.size()-1;
availableConnections.removeElementAt(lastIndex);
// If connection on available list is closed (e.g.,it timed out), then
// remove it from available list and repeat the process of obtaining a
// connection.Also wake up threads that were waiting for a connection
// because maxConnection limit was reached.
if (existingConnection.isClosed()) {
Logger.debug("Exist connection closed, notify all and get a new free connection.");
notifyAll(); // Freed up a spot for anybody waiting
return(getActiveConnection());
} else {
busyConnections.addElement(existingConnection);
// debug when connection get.
Logger.debug("Get connection successfully!");
Logger.debug("Total connection: ");
Logger.debug(""+this.totalConnections());
Logger.debug("Available connections: ");
Logger.debug(""+availableConnections.size());
Logger.debug("Busy connections: ");
Logger.debug(""+busyConnections.size());
Logger.debug("");
return(existingConnection);
}
} else {
// Three possible cases:
// 1) You haven't reached maxConnections limit. So
// establish one in the background if there isn't
// already one pending, then wait for
// the next available connection (whether or not
// it was the newly established one).
// 2) You reached maxConnections limit and waitIfBusy
// flag is false. Throw SQLException in such a case.
// 3) You reached maxConnections limit and waitIfBusy
// flag is true. Then do the same thing as in second
// part of step 1: wait for next available connection.
if ((totalConnections()<maxConnections)&&!connectionPending) {
makeBackgroundConnection();
} else if (!waitIfBusy) {
throw new SQLException("com.yup.lib.dataaccess.ConnectionPool.getActiveConnection(): "+EX_LIMIT_REACHED);
}
// Wait for either a new connection to be established
// (if you called makeBackgroundConnection) or for
// an existing connection to be freed up.
try {
Logger.debug("No Availible Connection, Waiting...");
wait();
} catch(InterruptedException ie) {}
// Someone freed up a connection, so try again.
return(getActiveConnection());
}
}
// You can't just make a new connection in the foreground
// when none are available, since this can take several
// seconds with a slow network connection. Instead,
// start a thread that establishes a new connection,
// then wait. You get woken up either when the new connection
// is established or if someone finishes with an existing
// connection.
private void makeBackgroundConnection() {
connectionPending = true;
try {
Thread connectThread = new Thread(this);
connectThread.start();
} catch(OutOfMemoryError ex) {
Logger.debug("com.yup.lib.dataaccess.ConnectionPool.makeBackgroundConnection(): Out of memory error:" + ex.toString());
// Give up on new connection
}
}
// start a thread.
public void run() {
try {
Connection connection = makeNewConnection();
synchronized(this) {
availableConnections.addElement(connection);
connectionPending = false;
notifyAll();
}
} catch(Exception ex) { // SQLException or OutOfMemory
// Give up on new connection and wait for existing one
// to free up.
Logger.debug("com.yup.lib.dataaccess.ConnectionPool.run(): " + ex.toString());
}
}
// This explicitly makes a new connection. Called in
// the foreground when initializing the ConnectionPool,
// and called in the background when running.
private Connection makeNewConnection()
throws SQLException {
// Establish network connection to database
Connection connection = DriverManager.getConnection(url, username, password);
Logger.debug("Make new connection successfully!");
return(connection);
}
// Driver loading.
private void loadDriver()
throws SQLException {
try {
// Load database driver if not already loaded
drvDriver = (Driver)Class.forName(driver).newInstance();
DriverManager.registerDriver(drvDriver);
Logger.debug("Load driver succcessfully!");
} catch(ClassNotFoundException ex) {
// Simplify try/catch blocks of people using this by
// throwing only one exception type.
throw new SQLException("com.yup.lib.dataaccess.ConnectionPool.makeNewConnection():" + EX_DRIVER_NOT_FOUND + driver);
} catch(IllegalAccessException ex) {
// Simplify try/catch blocks of people using this by
// throwing only one exception type.
throw new SQLException("com.yup.lib.dataaccess.ConnectionPool.makeNewConnection():" + ex.getMessage());
} catch(InstantiationException ex) {
// Simplify try/catch blocks of people using this by
// throwing only one exception type.
throw new SQLException("com.yup.lib.dataaccess.ConnectionPool.makeNewConnection():" + ex.getMessage());
}
}
// Driver releasing.
private void releaseDriver()
throws SQLException {
DriverManager.deregisterDriver(drvDriver);
Logger.debug("Release driver succcessfully!");
}
// Free up a connection.
public synchronized void freeConnection(Connection connection) {
busyConnections.removeElement(connection);
availableConnections.insertElementAt(connection,0);
// Wake up threads that are waiting for a connection
Logger.debug("Free connection successfully, notifying...");
Logger.debug("Total connection: ");
Logger.debug(""+totalConnections());
Logger.debug("Available connections: ");
Logger.debug(""+availableConnections.size());
Logger.debug("Busy connections: ");
Logger.debug(""+busyConnections.size());
// reach up limit.release.
if(++freeTimes>reuseUpLimit) {
freeTimes = 0;
Logger.debug("================ Time to close some fatigued connections ===============");
try {
connection.close();
} catch (SQLException ex) {
Logger.debug("com.yup.lib.dataaccess.ConnectionPool.freeConnection(): " + ex.toString());
}
}
// Available Connection
Logger.debug("======================");
Logger.debug("========== " + (reuseUpLimit-freeTimes) + " ========");
Logger.debug("======================");
notifyAll();
}
// Get the count of current connections.
public synchronized int totalConnections() {
int intTotal = availableConnections.size() + busyConnections.size();
return intTotal;
}
/** Close all the connections. Use with caution:
* be sure no connections are in use before
* calling. Note that you are not <I>required</I> to
* call this when done with a ConnectionPool, since
* connections are guaranteed to be closed when
* garbage collected. But this method gives more control
* regarding when the connections are closed.
*/
private synchronized void closeAllConnections() {
this.closeConnections(availableConnections);
availableConnections = new Vector();
this.closeConnections(busyConnections);
busyConnections = new Vector();
}
// Destroy the pool.
public static void destory()
throws SQLException {
if(pool==null) {
throw new SQLException("com.yup.lib.dataaccess.destory(): " + EX_POOL_NOT_INIT);
}
pool.closeAllConnections();
pool.availableConnections = null;
pool.busyConnections = null;
pool.releaseDriver();
pool = null;
}
// Close up all the connections.
private void closeConnections(Vector connections) {
try {
for (int i=0; i<connections.size(); i++) {
Connection connection = (Connection)connections.elementAt(i);
if ( !connection.isClosed() ) {
Logger.debug("Connection closed succcessfully!");
connection.close();
}
}
} catch(SQLException ex) {
Logger.debug("com.yup.lib.dataaccess.ConnectionPool.freeConnection(): " + ex.toString());
// Ignore errors; garbage collect anyhow
}
}
// Get info.
public String toString() {
String info =
"ConnectionPool(" + url + "," + username + ")" +
", available=" + availableConnections.size() +
", busy=" + busyConnections.size() +
", max=" + maxConnections;
return(info);
}
// a test method.
public static void main(String[] args) {
try {
String url="jdbc:odbc:Driver=Microsoft Access Driver (*.mdb);DBQ=D:\\__!!MILES!!__\\dev\\jdbc\\xxx.mdb";
String driver = "sun.jdbc.odbc.JdbcOdbcDriver";
Global.initDBPool(driver, url);
} catch(Exception ex) {
ex.printStackTrace();
} finally {
try{
Global.destoryDBPool();
} catch(SQLException ex) {
ex.printStackTrace();
}
}
}
}