一个连接池的例子(来自JIVE)(2)
发表于:2007-07-01来源:作者:点击数:
标签:
//文件:DbConnectionDefaultPool. java 的第二部分 /** * Housekeeping thread.Runs in the background with low CPU overhead. * Connections are checked for warnings and closure and are periodically * restarted. * This thread is a catchall for co
//文件:DbConnectionDefaultPool.
java的第二部分
/**
* Housekeeping thread. Runs in the background with low CPU overhead.
* Connections are checked for warnings and closure and are periodically
* restarted.
* This thread is a catchall for cor
rupted
* connections and prevents the buildup of open cursors. (Open cursors
* result when the application fails to close a Statement).
* This method acts as fault tolerance for bad connection/statement programming.
*/
public void run() {
boolean forever = true;
Statement stmt=null;
String currCatalog=null;
while(forever) {
// Make sure the log file is the one this instance opened
// If not, clean it up!
try {
BufferedReader in = new BufferedReader(new
FileReader(logFileString + "pid"));
String curr_pid = in.readLine();
if(curr_pid.equals(pid)) {
//log.println("They match = " + curr_pid);
}
else {
//log.println("No match = " + curr_pid);
log.close();
// Close all connections silently - they are definitely dead.
for(int i=0; i < currConnections; i++) {
try {
connPool[i].close();
}
catch (
SQLException e1) {} // ignore
}
// Returning from the run() method kills the thread
return;
}
in.close();
}
catch (IOException e1) {
log.println("Can@#t read the file for pid info: " +
logFileString + "pid");
}
// Get any Warnings on connections and print to event file
for(int i=0; i < currConnections; i++) {
try {
currSQLWarning = connPool[i].getWarnings();
if(currSQLWarning != null) {
log.println("Warnings on connection " +
String.valueOf(i) + " " + currSQLWarning);
connPool[i].clearWarnings();
}
}
catch(SQLException e) {
log.println("Cannot a
clearcase/" target="_blank" >ccess Warnings: " + e);
}
}
for(int i=0; i < currConnections; i++) { // Do for each connection
long age = System.currentTimeMillis() - connCreateDate[i];
synchronized(connStatus) {
if(connStatus[i] > 0) { // In use, catch it next time!
continue;
}
connStatus[i] = 2; // Take offline (2 indicates housekeeping lock)
}
try { // Test the connection with createStatement call
if(age > maxConnMSec) { // Force a reset at the max conn time
throw new SQLException();
}
stmt = connPool[i].createStatement();
connStatus[i] = 0; // Connection is O.K.
//log.println("Connection confirmed for conn = " +
// String.valueOf(i));
// Some DBs return an object even if DB is shut down
if(connPool[i].isClosed()) {
throw new SQLException();
}
// Connection has a problem, restart it
}
catch(SQLException e) {
try {
log.println(new Date().toString() +
" ***** Recycling connection " +
String.valueOf(i) + ":");
connPool[i].close();
createConn(i);
}
catch(SQLException e1) {
log.println("Failed: " + e1);
connStatus[i] = 0; // Can@#t open, try again next time
}
}
finally {
try {
if(stmt != null) {
stmt.close();
}
}
catch(SQLException e1){};
}
}
try {
Thread.sleep(20000);
} // Wait 20 seconds for next cycle
catch(InterruptedException e) {
// Returning from the run method sets the internal
// flag referenced by Thread.isAlive() to false.
// This is required because we don@#t use stop() to
// shu
tdown this thread.
return;
}
}
} // End run
/**
* This method hands out the connections in round-robin order.
* This prevents a faulty connection from locking
* up an application entirely. A browser @#refresh@# will
* get the next connection while the faulty
* connection is cleaned up by the housekeeping thread.
*
* If the min number of threads are ever exhausted, new
* threads are added up the the max thread count.
* Finally, if all threads are in use, this method waits
* 2 seconds and tries again, up to ten times. After that, it
* returns a null.
*/
public Connection getConnection() {
Connection conn=null;
if(available){
boolean gotOne = false;
for(int outerloop=1; outerloop<=10; outerloop++) {
try {
int loop=0;
int roundRobin = connLast + 1;
if(roundRobin >= currConnections) roundRobin=0;
do {
synchronized(connStatus) {
if((connStatus[roundRobin] < 1) &&
(! connPool[roundRobin].isClosed()))
{
conn = connPool[roundRobin];
connStatus[roundRobin]=1;
connLockTime[roundRobin] =
System.currentTimeMillis();
connLast = roundRobin;
gotOne = true;
break;
}
else {
loop++;
roundRobin++;
if(roundRobin >= currConnections) roundRobin=0;
}
}
}
while((gotOne==false)&&(loop < currConnections));
}
catch (SQLException e1) {}
if(gotOne) {
break;
}
else {
synchronized(this) { // Add new connections to the pool
if(currConnections < maxConns) {
try {
createConn(currConnections);
currConnections++;
}
catch(SQLException e) {
log.println("Unable to create new connection: " + e);
}
}
}
try { Thread.sleep(2000); }
catch(InterruptedException e) {}
log.println("-----> Connections Exhausted! Will wait and try " +
"again in loop " +
String.valueOf(outerloop));
}
} // End of try 10 times loop
}
else {
log.println("Unsuccessful getConnection() request during destroy()");
} // End if(available)
return conn;
}
/**
* Returns the local JDBC ID for a connection.
*/
public int idOfConnection(Connection conn) {
int match;
String tag;
try {
tag = conn.toString();
}
catch (NullPointerException e1) {
tag = "none";
}
match=-1;
for(int i=0; i< currConnections; i++) {
if(connID[i].equals(tag)) {
match = i;
break;
}
}
return match;
}
/**
* Frees a connection. Replaces connection back into the main pool for
* reuse.
*/
public String freeConnection(Connection conn) {
String res="";
int thisconn = idOfConnection(conn);
if(thisconn >= 0) {
connStatus[thisconn]=0;
res = "freed " + conn.toString();
//log.println("Freed connection " + String.valueOf(thisconn) +
// " normal exit: ");
}
else {
log.println("----> Could not free connection!!!");
}
return res;
}
原文转自:http://www.ltesting.net