动网论坛,站长建站首选,国内使用量最多的论坛软件 动网论坛官方技术讨论区 站长工具 申请属于您自己的免费论坛
首页 | 新闻资讯 | 网站运营 | 网络编程 | 数据库 | 服务器 | 网页设计 | 图像媒体 | 网络应用 | 搜索优化 | 资源下载 | 动网主机 | DVBOX
    本站内  互联网 ASP论坛  ASP.Net论坛  PHP论坛
  
   Jsp → 阅读文章

 一个连接池的例子 (二)

作者来源: 
阅读 1378 人次 , 2006-3-29 4:23:00 


/**
 * 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;
}

//文件:dbconnectiondefaultpool.java的第三部分


/**
 * returns the age of a connection -- the time since it was handed out to
 * an application.
 */
public long getage(connection conn) { // returns the age of the connection in millisec.
int thisconn = idofconnection(conn);
return system.currenttimemillis() - connlocktime[thisconn];
}

private void createconn(int i) throws sqlexception {
 date now = new date();
 try {
class.forname (dbdriver);
properties dbprop = new properties();
//log.println("creating.....");
dbprop.put("user", dblogin);
dbprop.put("password", dbpassword);
dbprop.put("characterencoding","gb2112");
//dbprop.put("useunicode", "true");

connpool[i] = drivermanager.getconnection
(dbserver,dbprop);
//log.println("created ok...");
connstatus[i]=0;
connid[i]=connpool[i].tostring();
connlocktime[i]=0;
conncreatedate[i] = now.gettime();
}
catch (classnotfoundexception e2) {}

log.println(now.tostring() + " opening connection " + string.valueof(i) +
" " + connpool[i].tostring() + ":");
}

/**
 * shuts down the housekeeping thread and closes all connections
 * in the pool. call this method from the destroy() method of the servlet.
 */

/**
 * multi-phase shutdown. having following sequence:
 * <ol>
 * <li><code>getconnection()</code> will refuse to return connections.
 * <li>the housekeeping thread is shut down.<br>
 * up to the time of <code>millis</code> milliseconds after shutdown of
 * the housekeeping thread, <code>freeconnection()</code> can still be
 * called to return used connections.
 * <li>after <code>millis</code> milliseconds after the shutdown of the
 * housekeeping thread, all connections in the pool are closed.
 * <li>if any connections were in use while being closed then a
 * <code>sqlexception</code> is thrown.
 * <li>the log is closed.
 * </ol><br>
 * call this method from a servlet destroy() method.
 *
 * @param millis  the time to wait in milliseconds.
 * @exception sqlexception if connections were in use after
 * <code>millis</code>.
 */
public void destroy(int millis) throws sqlexception {

// checking for invalid negative arguments is not necessary,
// thread.join() does this already in runner.join().

// stop issuing connections
available=false;

// shut down the background housekeeping thread
runner.interrupt();

// wait until the housekeeping thread has died.
try { runner.join(millis); }
catch(interruptedexception e){} // ignore

// the housekeeping thread could still be running
// (e.g. if millis is too small). this case is ignored.
// at worst, this method will throw an exception with the
// clear indication that the timeout was too short.

long starttime=system.currenttimemillis();

// wait for freeconnection() to return any connections
// that are still used at this time.
int usecount;
while((usecount=getusecount())>0 && system.currenttimemillis() - starttime <= millis) {
try { thread.sleep(500); }
catch(interruptedexception e) {} // ignore
}

// close all connections, whether safe or not
for(int i=0; i < currconnections; i++) {
try {
connpool[i].close();
}
catch (sqlexception e1)
{
log.println("cannot close connections on destroy");
}
}

if(usecount > 0) {
//bt-test successful
string msg="unsafe shutdown: had to close "+usecount+
" active db connections after "+millis+"ms";
log.println(msg);
// close all open files
log.close();
// throwing following exception is essential because servlet authors
// are likely to have their own error logging requirements.
throw new sqlexception(msg);
}

// close all open files
log.close();

}//end destroy()


/**
 * less safe shutdown. uses default timeout value.
 * this method simply calls the <code>destroy()</code> method
 * with a <code>millis</code>
 * value of 10000 (10 seconds) and ignores <code>sqlexception</code>
 * thrown by that method.
 * @see  #destroy(int)
 */
public void destroy() {
try {
destroy(10000);
}
catch(sqlexception e) {}
}

/**
 * returns the number of connections in use.
 */
// this method could be reduced to return a counter that is
// maintained by all methods that update connstatus.
// however, it is more efficient to do it this way because:
// updating the counter would put an additional burden on the most
// frequently used methods; in comparison, this method is
// rarely used (although essential).
public int getusecount() {
int usecount=0;
synchronized(connstatus) {
for(int i=0; i < currconnections; i++) {
if(connstatus[i] > 0) { // in use
usecount++;
}
}
}
return usecount;
}//end getusecount()

/**
 * returns the number of connections in the dynamic pool.
 */
public int getsize() {
return currconnections;
}//end getsize()

}

/**
 * an implementation of the connection interface that wraps an underlying
 * connection object. it releases the connection back to a connection pool
 * when connection.close() is called.
 */
public class connectionwrapper implements connection {

private connection connection;
private connectionpool connectionpool;

public connectionwrapper(connection connection, connectionpool connectionpool) {
this.connection = connection;
this.connectionpool = connectionpool;
}

/**
 * instead of closing the underlying connection, we simply release
 * it back into the pool.
 */
public void close() throws sqlexception {
connectionpool.freeconnection(this.connection);
//release object references. any further method calls on the
//connection will fail.
connection = null;
connectionpool = null;
}

public statement createstatement() throws sqlexception {
return connection.createstatement();
}

public preparedstatement preparestatement(string sql) throws sqlexception {
return connection.preparestatement(sql);
}

public callablestatement preparecall(string sql) throws sqlexception {
return connection.preparecall(sql);
}

public string nativesql(string sql) throws sqlexception {
return connection.nativesql(sql);
}

public void setautocommit(boolean autocommit) throws sqlexception {
connection.setautocommit(autocommit);
}

public boolean getautocommit() throws sqlexception {
return connection.getautocommit();
}

public void commit() throws sqlexception {
connection.commit();
}

public void rollback() throws sqlexception {
connection.rollback();
}

public boolean isclosed() throws sqlexception {
return connection.isclosed();
}

public databasemetadata getmetadata() throws sqlexception {
return connection.getmetadata();
}

public void setreadonly(boolean readonly) throws sqlexception {
connection.setreadonly(readonly);
}

public boolean isreadonly() throws sqlexception {
return connection.isreadonly();
}

public void setcatalog(string catalog) throws sqlexception {
connection.setcatalog(catalog);
}

public string getcatalog() throws sqlexception {
return connection.getcatalog();
}

public void settransactionisolation(int level) throws sqlexception {
connection.settransactionisolation(level);
}

public int gettransactionisolation() throws sqlexception {
return connection.gettransactionisolation();
}

public sqlwarning getwarnings() throws sqlexception {
return connection.getwarnings();
}

public void clearwarnings() throws sqlexception {
connection.clearwarnings();
}

public statement createstatement(int resultsettype, int resultsetconcurrency)
throws sqlexception
{
return connection.createstatement(resultsettype, resultsetconcurrency);
}

public preparedstatement preparestatement(string sql, int resultsettype,
int resultsetconcurrency) throws sqlexception
{
return connection.preparestatement(sql, resultsettype, resultsetconcurrency);
}

public callablestatement preparecall(string sql, int resultsettype,
int resultsetconcurrency) throws sqlexception
{
return preparecall(sql, resultsettype, resultsetconcurrency);
}

public map gettypemap() throws sqlexception {
return connection.gettypemap();
}

public void settypemap(map map) throws sqlexception {
connection.settypemap(map);
}

}
} //文件:dbconnectionmanager.java

package com.qingtuo.db.pool;

import java.sql.*;
import java.io.*;
import java.util.*;

/**
* central manager of database connections.
*/
public class dbconnectionmanager {

private static dbconnectionprovider connectionprovider;
private static object providerlock = new object();

/**
 * returns a database connection from the currently active connection
 * provider.
 */
public static connection getconnection() {
if (connectionprovider == null) {
synchronized (providerlock) {
if (connectionprovider == null) {
//create the connection provider -- for now, this is hardcoded. for
//the next beta, i'll change this to load up the provider dynamically.
connectionprovider = new dbconnectiondefaultpool();
connectionprovider.start();
}
}
}
connection con = connectionprovider.getconnection();
if (con == null) {
system.err.println("warning: dbconnectionmanager.getconnection() failed to obtain a connection.");
}
return con;
}

/**
 * returns the current connection provider. the only case in which this
 * method should be called is if more information about the current
 * connection provider is needed. database connections should always be
 * obtained by calling the getconnection method of this class.
 */
public static dbconnectionprovider getdbconnectionprovider() {
return connectionprovider;
}

/**
 * sets the connection provider. the old provider (if it exists) is shut
 * down before the new one is started. a connection provider <b>should
 * not</b> be started before being passed to the connection manager.
 */
public static void setdbconnectionprovider(dbconnectionprovider provider) {
synchronized (providerlock) {
if (connectionprovider != null) {
connectionprovider.destroy();
connectionprovider = null;
}
connectionprovider = provider;
provider.start();
}
}


}
 
 收藏本文  打印本文  论坛讨论  关闭窗口
· 上一篇:jsp+beans实现读取数据库的例子
· 下一篇:一个连接池的例子 (一)
· JSP内幕
· JAVA/JSP学习系列之十一
· JSP+XML构架网站的实例
· Taglib 原理和实现之什么是Taglib
· IBM WebSphere源代码暴露漏洞


关于本站 | 联系我们 | 业务合作 | 客户案例 | 诚聘英才 | 广告合作 | 收藏本站
海口动网先锋网络科技有限公司版权所有
Copyright © 2000 - 2006 Cndw.Com
中华人民共和国电信与信息服务业务经营许可证编号 琼 ICP 020077