大家看我这段代码有什么问题么?

05-10-24 escape
package org.jelly.pool.impl;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.sql.Connection;
import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.LinkedList;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import org.jelly.pool.AbstractConnectionPool;
import org.jelly.pool.exceptions.ServerShutDownException;

public class ConnectionPoolImpl extends AbstractConnectionPool {

private static Log logger = LogFactory.getLog(ConnectionPoolImpl.class);

// jdbc相当的参数声明
private String jdbcUserName;
private String jdbcPassword;
private String jdbcUrl;
private String jdbcDriverClass;

// 连接池大小的控制变量声明
private int minimum;
private int maximum;
private static final int DEFAULT_SIZE = 100;
private static final int DEFAULT_MIN_SIZE = 100;
private static final int DEFAULT_MAX_SIZE = 300;
private static final int DEFAULT_WAIT_TIMEOUT = 1000;
private static final String DEFAULT_METHOD_CLOSE = "close";

// 存放数据库连接的集合
private List usedConnection;
private List availableConnection;

// 连接池的标志位
private boolean isShutDown = false;

// 线程对像
private Thread woker = null;

// lock object
Object lock = new Object();

public ConnectionPoolImpl(String jdbcUserName, String jdbcPassword, String jdbcUrl, String jdbcDriverClass, int minimum, int maximum) {
this.jdbcUserName = jdbcUserName;
this.jdbcPassword = jdbcPassword;
this.jdbcUrl = jdbcUrl;
this.jdbcDriverClass = jdbcDriverClass;
this.minimum = minimum;
this.maximum = maximum;
usedConnection = new LinkedList();
availableConnection = new LinkedList();
System.out.println("connection pool is started...");
System.out.println("jdbcUserName: " + jdbcUserName);
System.out.println("jdbcPassword: " + jdbcPassword);
System.out.println("jdbcUrl: " + jdbcUrl);
System.out.println("jdbcDriverClass: " + jdbcDriverClass);
try {
Driver driver = (Driver)Class.forName(jdbcDriverClass).newInstance();
DriverManager.registerDriver(driver);
makeMinimumConnection(minimum);
} catch (SQLException ex) {
throw new RuntimeException("cannot register jdbc driver or cannot get conection.");
} catch (ClassNotFoundException cnfe) {
throw new RuntimeException("cannot found driver class: ['" + jdbcDriverClass + "'].");
} catch(InstantiationException ie) {
throw new RuntimeException("canoot instance object");
} catch(IllegalAccessException lae) {
throw new RuntimeException("access dined");
}

startThread();
}

// public ConnectionPoolImpl(String jdbcUserName, String jdbcPassword, String jdbcUrl, String jdbcDriverClass, int minimum) {
// this(jdbcUserName, jdbcPassword, jdbcUrl, jdbcDriverClass, minimum, DEFAULT_MAX_SIZE);
// }
//
// public ConnectionPoolImpl(String jdbcUserName, String jdbcPassword, String jdbcUrl, String jdbcDriverClass, int maximum) {
// this(jdbcUserName, jdbcPassword, jdbcUrl, jdbcDriverClass, minimum, DEFAULT_MIN_SIZE);
// }

public ConnectionPoolImpl(String jdbcUserName, String jdbcPassword, String jdbcUrl, String jdbcDriverClass) {
this(jdbcUserName, jdbcPassword, jdbcUrl, jdbcDriverClass, DEFAULT_MIN_SIZE, DEFAULT_MAX_SIZE);
}

// 启动连接池线程,子类必须H这个方法.
protected void startThread() {
woker = new Thread(this);
System.out.println("start thread...");
woker.start();
}

// 创建最小连接的数.
protected int makeMinimumConnection(int minimum) throws SQLException {
for (int i = 0; i < minimum; i++) {
System.out.println("iterator i: " + i);
availableConnection.add(makeConnection());
}
return 0;
}

protected void loop() {
System.out.println("loop");
while (!isShutDown) {
if (minimum < getAvailableSize()) {
for (int i = 0; i < getAvailableSize(); i++) {
Connection conn = (Connection)availableConnection.remove(0);
try {
conn.close();
} catch (SQLException ex) {
throw new RuntimeException("cannot close connection");
}
}
} else {
for (int i = getAvailableSize(); i < minimum; i++) {
try {
availableConnection.add(makeConnection());
} catch (SQLException ex) {
throw new RuntimeException("cannot create connection for pool");
}
}
}
try {
lock.wait(DEFAULT_WAIT_TIMEOUT);
} catch (InterruptedException ie) {
throw new RuntimeException("error");
}
System.out.println("available connection total is: " + getAvailableSize());
}
}

protected void shutDown() {

}

private Connection makeConnection() throws SQLException {
//_Connection conn = null;
if (jdbcUserName.length() > 0) {
System.out.println("create connection proxy for pool");
return new _Connection(DriverManager.getConnection( jdbcUrl, jdbcUserName, jdbcPassword)).getConnection();
} else {
return new _Connection(DriverManager.getConnection(jdbcUrl)).getConnection();
}
}

private Connection getInternalConnection() {
Connection result = null;
if (!availableConnection.isEmpty()) {
result = (Connection)availableConnection.remove(0);
} else if (usedConnection.size() < maximum) {
try {
result = makeConnection();
} catch (SQLException ex) {
throw new RuntimeException("cannot create connection for pool");
}
}
if (null != result) {
usedConnection.add(result);
}

return result;
}

private int getAvailableSize() {
return availableConnection.size();
}

private int getTotal() {
return (availableConnection.size() + usedConnection.size());
}

public synchronized Connection getConnection() {
if (isShutDown) {
throw new ServerShutDownException("the connection pool was shut down...");
}
Connection result = getInternalConnection();
return result;
}

public void exit() {
isShutDown = true;
}

public int getMinimum() {
return this.minimum;
}

public int getMaximum() {
return this.maximum;
}

/* (non-Javadoc)
* @see org.jelly.pool.ConnectionPool#getConnectionWaitTime(int)
*/
public Connection getConnectionWaitTime(int time) {
// TODO Auto-generated method stub
return null;
}
private class _Connection implements InvocationHandler {

private Connection conn;

public _Connection(Connection conn) {
this.conn = conn;
}

public Connection getConnection() {
//this.conn = conn;
return (Connection)Proxy.newProxyInstance( conn.getClass().getClassLoader(), conn.getClass().getInterfaces(), this);
}

public Object invoke(Object proxy, Method m, Object[] args) {
System.out.println(m.getName());
Object obj = null;
if (DEFAULT_METHOD_CLOSE.equals(m.getName()) && minimum > getAvailableSize()) {
availableConnection.add(conn);
lock.notify();
} else {
try {
obj = m.invoke(conn, args);
}catch(IllegalAccessException el) {

}catch(IllegalArgumentException ia) {

}catch(InvocationTargetException ite) {

}
}

return obj;
}
}
}

lock.wait();这一句说
Exception in thread "Thread-1" java.lang.IllegalMonitorStateException: current thread not owner
是什么意思呢?

banq
2005-10-25 15:42
永远不要自己编写数据库连接池,很多初学者被很多Java文章误导,致使白花费大量时间在学习上,而且进步不大。

你只要会调用连接池以及配置连接池即可。

wjhandboy
2005-10-25 17:23
有道理.

escape
2005-10-25 23:48
首先我要谢谢banq, 其次我要告诉banq, 我不是初学者,在次, 因为觉得挺有趣,我想实现一下,在实际的开发中,我从来都是用AppServer的数据源的。

yellowicq
2005-10-26 10:39
lock.wait();这一句

必须放到synchronize(lock)里面

synchronized(lock){
  lock.wait();
}
<p class="indent">

escape
2005-10-26 12:38
谢谢楼上,问题已经解决了,我手误了一个地方,