JiveJdon Community Forums
在线81人 J道首页 | 论坛首页 | 培训咨询 | 开源框架 | 精华 | 查搜 | 注册 | 登陆 |
首页 » 论坛 » 设计模式、框架和架构
???en_US.forumThreadPrev.name??? 上一主题
Go back to the topic listing   返回主题列表
???en_US.forumThreadNext.name??? 下一主题
这个主题共有 18 回复 / 2 页 [ 1 2 下一页 ]  发表新帖子  回复该主题贴
CrazyJavar

发表文章: 30
注册时间: 2002年09月18日 00:20
[寻]连接池例子 发表: 2002年09月28日 11:16 回复


要求:

1.可以不依赖于任何特殊J2EE Server

2.代码越短越好

3.性能不要太差

4.有文档最好

哪位高手可以给个例子?
wait4friend

发表文章: 37
注册时间: 2002年08月22日 09:35
Re: [寻]连接池例子 发表: 2002年09月28日 14:06 回复
Utilities.zip
cc

发表文章: 279
注册时间: 2002年08月07日 23:47
Re: [寻]连接池例子 发表: 2002年09月28日 14:30 回复
讲讲思路吧。
wait4friend

发表文章: 37
注册时间: 2002年08月22日 09:35
Re: [寻]连接池例子 发表: 2002年09月28日 15:27 回复
uitl.database.ConnectionManager
用队列保存min个连接,尾进头出。getConnection()检查队列中如有,从头弹出,如果这时候没有可用的,循环等待指定时间,如果还是没有(异常),返回null。后台的线程检查队列中的可用连接数目是否小于min,如果小于,生成并在队列尾部插入min-size个连接。用户freeConnection,如果size<max,插入尾部,否则释放。
wait4friend

发表文章: 37
注册时间: 2002年08月22日 09:35
Re: [寻]连接池例子 发表: 2002年09月28日 15:30 回复
用户freeConnection(conn),如果size 不小于max,插入队列尾部,否则释放这个conn
Sean

发表文章: 22
注册时间: 2002年09月17日 13:26
Re: [寻]连接池例子 发表: 2002年09月29日 13:34 回复
uitl.database.ConnectionManager
没有设置size的方法?
这是很奇怪的
wait4friend

发表文章: 37
注册时间: 2002年08月22日 09:35
Re: [寻]连接池例子 发表: 2002年09月29日 15:21 回复
uitl.database.ConnectionManager.getInstance()要求提供min和max,如果需要在运行中改变,可以自己加入setMin()之类的方法。
CrazyJavar

发表文章: 30
注册时间: 2002年09月18日 00:20
Re: [寻]连接池例子 发表: 2002年09月30日 10:24 回复
我想把你的例子改成就一个类ConnectionPool,没有内部类,你说可能吗?
CrazyJavar

发表文章: 30
注册时间: 2002年09月18日 00:20
Re: [寻]连接池例子 发表: 2002年09月30日 11:07 回复
还有,请教一下你在getConnection中的

//等待半个周期
wait(PERIOD / 2);

,但是整个程序中,并没有notify或者notifyAll语句啊
Java狐狸

发表文章: 7
注册时间: 2002年09月17日 11:31
Re: [寻]连接池例子 发表: 2002年09月30日 14:05 回复
public static Connection getConnection()
throws Exception
{
Connection connection = null;
if (connectionPool.size() < NUM_OF_CONNECTION)
{
connection = Class.forName("my.sql.Driver"). getConnection("dbc:oracle:thin:@192.168.0.164:1521:ora9i"); connectionPool.add(connection);
}
else {
if(conuter < NUM_OF_CONNECTION) counter++;
else counter = 0;
connection = (Connection)connectionPool.elementAT(counter% NUM_OF_CONNECTION );
}
return connection;
}
wait4friend

发表文章: 37
注册时间: 2002年08月22日 09:35
Re: [寻]连接池例子 发表: 2002年09月30日 14:36 回复
Re;"但是整个程序中,并没有notify或者notifyAll语句啊 "
哈哈,说句老实话,我对Thread这个东西真的不熟悉,到底有没有正确使用我不敢保证。是不是应该在run()里面增加可用连接后,notify()一下?我不知道这个, 请你指教。
java_edge@msn.com

发表文章: 1
注册时间: 2002年10月02日 15:46
Re: [寻]连接池例子 发表: 2002年10月02日 15:48 回复
import java.io.*;
import java.sql.*;
import java.text.*;
import java.util.Date;


/**
* DbConnectionBroker
* A servlet-based broker for database connections.
* Creates and manages a pool of database connections.
* @version 1.0.13 3/12/02
* @author Marc A. Mnich
*/
public class DbConnectionBroker implements Runnable {
private Thread runner;

private Connection[] connPool;
private int[] connStatus;

private long[] connLockTime, connCreateDate;
private String[] connID;
private String dbDriver, dbServer, dbLogin, dbPassword, logFileString;
private int currConnections, connLast, minConns, maxConns, maxConnMSec,
maxCheckoutSeconds, debugLevel;

//available: set to false on destroy, checked by getConnection()
private boolean available=true;

private PrintWriter log;
private SQLWarning currSQLWarning;
private String pid;

private final int DEFAULTMAXCHECKOUTSECONDS=60;
private final int DEFAULTDEBUGLEVEL=2;

/**
* Creates a new Connection Broker<br>
* dbDriver: JDBC driver. e.g. 'oracle.jdbc.driver.OracleDriver'<br>
* dbServer: JDBC connect string. e.g. 'jdbc:oracle:thin:@203.92.21.109:1526:orcl'<br>
* dbLogin: Database login name. e.g. 'Scott'<br>
* dbPassword: Database password. e.g. 'Tiger'<br>
* minConns: Minimum number of connections to start with.<br>
* maxConns: Maximum number of connections in dynamic pool.<br>
* logFileString: Absolute path name for log file. e.g. 'c:/temp/mylog.log' <br>
* maxConnTime: Time in days between connection resets. (Reset does a basic cleanup)<br>
* logAppend: Append to logfile (optional)<br>
* maxCheckoutSeconds: Max time a connection can be checked out before being recycled. Zero value turns option off, default is 60 seconds.
* debugLevel: Level of debug messages output to the log file. 0 -> no messages, 1 -> Errors, 2 -> Warnings, 3 -> Information
*/
public DbConnectionBroker(String dbDriver, String dbServer, String dbLogin,
String dbPassword, int minConns, int maxConns,
String logFileString, double maxConnTime) throws IOException {

setupBroker(dbDriver, dbServer, dbLogin, dbPassword, minConns,
maxConns, logFileString, maxConnTime, false,
DEFAULTMAXCHECKOUTSECONDS, DEFAULTDEBUGLEVEL);
}

/*
* Special constructor to handle logfile append
*/
public DbConnectionBroker(String dbDriver, String dbServer, String dbLogin,
String dbPassword, int minConns, int maxConns,
String logFileString, double maxConnTime, boolean logAppend)
throws IOException {

setupBroker(dbDriver, dbServer, dbLogin, dbPassword, minConns,
maxConns, logFileString, maxConnTime, logAppend,
DEFAULTMAXCHECKOUTSECONDS, DEFAULTDEBUGLEVEL);
}

/*
* Special constructor to handle connection checkout expiration
*/
public DbConnectionBroker(String dbDriver, String dbServer, String dbLogin,
String dbPassword, int minConns, int maxConns,
String logFileString, double maxConnTime, boolean logAppend,
int maxCheckoutSeconds, int debugLevel)
throws IOException {

setupBroker(dbDriver, dbServer, dbLogin, dbPassword, minConns,
maxConns, logFileString, maxConnTime, logAppend,
maxCheckoutSeconds, debugLevel);
}



private void setupBroker(String dbDriver, String dbServer, String dbLogin,
String dbPassword, int minConns, int maxConns,
String logFileString, double maxConnTime, boolean logAppend,
int maxCheckoutSeconds, int debugLevel)
throws IOException {

connPool = new Connection[maxConns];
connStatus = new int[maxConns];
connLockTime = new long[maxConns];
connCreateDate = new long[maxConns];
connID = new String[maxConns];
currConnections = minConns;
this.maxConns = maxConns;
this.dbDriver = dbDriver;
this.dbServer = dbServer;
this.dbLogin = dbLogin;
this.dbPassword = dbPassword;
this.logFileString = logFileString;
this.maxCheckoutSeconds = maxCheckoutSeconds;
this.debugLevel = debugLevel;
maxConnMSec = (int)(maxConnTime * 86400000.0); //86400 sec/day
if(maxConnMSec < 30000) { // Recycle no less than 30 seconds.
maxConnMSec = 30000;
}


try {
log = new PrintWriter(new FileOutputStream(logFileString,
logAppend),true);

// Can't open the requested file. Open the default file.
} catch (IOException e1) {
try {
log = new PrintWriter(new FileOutputStream("DCB_" +
System.currentTimeMillis() + ".log",
logAppend),true);

} catch (IOException e2) {
throw new IOException("Can't open any log file");
}
}



// Write the pid file (used to clean up dead/broken connection)
SimpleDateFormat formatter
= new SimpleDateFormat ("yyyy.MM.dd G 'at' hh:mm:ss a zzz");
Date nowc = new Date();
pid = formatter.format(nowc);

BufferedWriter pidout = new BufferedWriter(new
FileWriter(logFileString + "pid"));
pidout.write(pid);
pidout.close();

log.println("-----------------------------------------");
log.println("-----------------------------------------");
log.println("Starting DbConnectionBroker Version 1.0.13:");
log.println("dbDriver = " + dbDriver);
log.println("dbServer = " + dbServer);
log.println("dbLogin = " + dbLogin);
log.println("log file = " + logFileString);
log.println("minconnections = " + minConns);
log.println("maxconnections = " + maxConns);
log.println("Total refresh interval = " + maxConnTime + " days");
log.println("logAppend = " + logAppend);
log.println("maxCheckoutSeconds = " + maxCheckoutSeconds);
log.println("debugLevel = " + debugLevel);
log.println("-----------------------------------------");


// Initialize the pool of connections with the mininum connections:
// Problems creating connections may be caused during reboot when the
// servlet is started before the database is ready. Handle this
// by waiting and trying again. The loop allows 5 minutes for
// db reboot.
boolean connectionsSucceeded=false;
int dbLoop=20;

try {
for(int i=1; i < dbLoop; i++) {
try {
for(int j=0; j < currConnections; j++) {
createConn(j);
}
connectionsSucceeded=true;
break;
} catch (SQLException e){
if(debugLevel > 0) {
log.println("--->Attempt (" + String.valueOf(i) +
" of " + String.valueOf(dbLoop) +
") failed to create new connections set at startup: ");
log.println(" " + e);
log.println(" Will try again in 15 seconds...");
}
try { Thread.sleep(15000); }
catch(InterruptedException e1) {}
}
}
if(!connectionsSucceeded) { // All attempts at connecting to db exhausted
if(debugLevel > 0) {
log.println("\r\nAll attempts at connecting to Database exhausted");
}
throw new IOException();
}
} catch (Exception e) {
throw new IOException();
}

// Fire up the background housekeeping thread

runner = new Thread(this);
runner.start();

}//End DbConnectionBroker()


/**
* 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;
long maxCheckoutMillis = maxCheckoutSeconds * 1000;


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.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.getWarnings();
if(currSQLWarning != null) {
if(debugLevel > 1) {
log.println("Warnings on connection " +
String.valueOf(i) + " " + currSQLWarning);
}
connPool.clearWarnings();
}
} catch(SQLException e) {
if(debugLevel > 1) {
log.println("Cannot access Warnings: " + e);
}
}

}

for(int i=0; i < currConnections; i++) { // Do for each connection
long age = System.currentTimeMillis() - connCreateDate;


try { // Test the connection with createStatement call
synchronized(connStatus) {
if(connStatus > 0) { // In use, catch it next time!

// Check the time it's been checked out and recycle
long timeInUse = System.currentTimeMillis() -
connLockTime;
if(debugLevel > 2) {
log.println("Warning. Connection " + i +
" in use for " + timeInUse +
" ms");
}
if(maxCheckoutMillis != 0) {
if(timeInUse > maxCheckoutMillis) {
if(debugLevel > 1) {
log.println("Warning. Connection " +
i + " failed to be returned in time. Recycling...");
}
throw new SQLException();
}
}

continue;
}
connStatus = 2; // Take offline (2 indicates housekeeping lock)
}


if(age > maxConnMSec) { // Force a reset at the max conn time
throw new SQLException();
}

stmt = connPool.createStatement();
connStatus = 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.isClosed()) {
throw new SQLException();
}


// Connection has a problem, restart it
} catch(SQLException e) {

if(debugLevel > 1) {
log.println(new Date().toString() +
" ***** Recycling connection " +
String.valueOf(i) + ":");
}

try {
connPool.close();
} catch(SQLException e0) {
if(debugLevel > 0) {
log.println("Error! Can't close connection! Might have been closed already. Trying to recycle anyway... (" + e0 + ")");
}
}

try {
createConn(i);
} catch(SQLException e1) {
if(debugLevel > 0) {
log.println("Failed to create connection: " + e1);
}
connStatus = 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) {
log.println("Error: " + e1);
}

if(gotOne) {
break;
} else {
synchronized(this) { // Add new connections to the pool
if(currConnections < maxConns) {

try {
createConn(currConnections);
currConnections++;
} catch(SQLException e) {
if(debugLevel > 0) {
log.println("Error: Unable to create new connection: " + e);
}
}
}
}

try { Thread.sleep(2000); }
catch(InterruptedException e) {}
if(debugLevel > 0) {
log.println("-----> Connections Exhausted! Will wait and try again in loop " +
String.valueOf(outerloop));
}
}

} // End of try 10 times loop

} else {
if(debugLevel > 0) {
log.println("Unsuccessful getConnection() request during destroy()");
}
} // End if(available)

if(debugLevel > 2) {
log.println("Handing out connection " +
idOfConnection(conn) + " --> " +
(new SimpleDateFormat("MM/dd/yyyy hh:mm:ss a")).format(new java.util.Date()));
}

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.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 {
if(debugLevel > 0) {
log.println("----> Error: Could not free connection!!!");
}
}

return res;

}

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

connPool = DriverManager.getConnection
(dbServer,dbLogin,dbPassword);

connStatus=0;
connID=connPool.toString();
connLockTime=0;
connCreateDate = now.getTime();
} catch (ClassNotFoundException e2) {
if(debugLevel > 0) {
log.println("Error creating connection: " + e2);
}
}

log.println(now.toString() + " Opening connection " + String.valueOf(i) +
" " + connPool.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.close();
} catch (SQLException e1) {
if(debugLevel > 0) {
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 > 0) { // In use
useCount++;
}
}
}
return useCount;
}//End getUseCount()

/**
* Returns the number of connections in the dynamic pool.
*/
public int getSize() {
return currConnections;
}//End getSize()

}// End class


CrazyJavar

发表文章: 30
注册时间: 2002年09月18日 00:20
Re: [寻]连接池例子 发表: 2002年10月08日 09:54 回复
to wait4friend :

哦,这样的话,那你的程序明显有问题

wait()后没有notify()怎么行,这些是搭配使用的

我想你的意思可能是sleep()吧
wait4friend

发表文章: 37
注册时间: 2002年08月22日 09:35
Re: [寻]连接池例子 发表: 2002年10月08日 10:44 回复
wait(int)和sleep()是不是都可以呢?
CrazyJavar

发表文章: 30
注册时间: 2002年09月18日 00:20
Re: [寻]连接池例子 发表: 2002年10月08日 12:12 回复
应该是sleep(int)吧

wait我记得一定要和notifyAll()一起使用的

我线程写得也不多

我去查查先
这个主题有 18 回复 / 2 页 [ 1 2 下一页 ]
???en_US.forumThreadPrev.name??? 上一主题
Go back to the topic listing   返回主题列表    返回页首  返回页首
???en_US.forumThreadNext.name??? 下一主题
热点TAG: AOP cache DDD EJB 集群 设计模式 Hibernate IOC JiveJdon OO RBAC Spring Struts
查询本论坛内 回复超过的热门帖子
快速发表回复
标题
 
粗体 斜体 下划线 插入图片 插入代码 插入url链接 插入附件
内容
 

解惑之道在J道 ,打造中国最具影响力的的企业软件社区
OpenSource JIVEJDON v3.0 Powered by JdonFramework Code © 2002-07 jdon.com

anti spam