一个连接池的例子(来自JIVE)(2) - 中国WEB开发者网络 (http://www.webasp.net) -- 技术教程 (http://www.webasp.net/article/) --- 一个连接池的例子(来自JIVE)(2) (http://www.webasp.net/article/8/7017.htm) |
| -- 作者:未知 -- 发布日期: 2003-07-26 |
| //文件: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 corrupted * 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 access 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 // shutdown 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; } |
| webasp.net |