`
yy59750901
  • 浏览: 1635 次
  • 性别: Icon_minigender_1
  • 来自: 天津
最近访客 更多访客>>
文章分类
社区版块
存档分类

写了一个简单的数据库连接池,请帮忙看一下

阅读更多
我是一个新手,第一次发帖,以前都是看别人的帖子。
我写了一个简单的数据库连接池实现,感觉有很多欠缺的地方,希望各位指点一下。十分感谢。
有四个类:
(1)连接池配置对象 Config
(2)连接池主类 ConnectionPool
(3)Properties读取类  PropertyReader
(4)异常类 DBPoolException


ConnectionPool.java
  public class ConnectionPool {
	
	private static Logger logger = Logger.getLogger(ConnectionPool.class);
	//当前已用连接数
	private static volatile int curConnections = 0;
	
	private static Config config = null;
	
	//初始化成功标志
	private static boolean initFlag = false;
	
	private static volatile Stack<Connection> conns;
	static {
		PropertyReader pr = null;

		try {
			pr = new PropertyReader("pool-config.properties");
			config = new Config();
			//设置数据库驱动
			config.setDriver(pr.getValue("driver"));
			//url
			config.setUrl(pr.getValue("url"));
			//uername
			config.setUsername(pr.getValue("username"));
			//password
			config.setPassword(pr.getValue("password"));
			//最大连接数
			if(pr.getValue("maxConnections") != null){
				config.setMaxConnections(Integer.valueOf(pr.getValue("maxConnections")));
			}
			//初始化时最小连接数
			if(pr.getValue("minConnections") != null){
				config.setMinConnections(Integer.valueOf(pr.getValue("minConnections")));
			}
			//返还连接时是否提交
			if(pr.getValue("autoCommitOnClose") != null){
				config.setAutoCommitOnClose(Boolean.valueOf(pr.getValue("autoCommitOnClose")));
			}
			//当连接池用完时客户端调用getConn()后等待获取新连接的时间 
			//Default: (100毫秒)
			if(pr.getValue("checkoutTimeout") != null){
				config.setCheckoutTimeout(Integer.valueOf(pr.getValue("checkoutTimeout")));
			}
			//当没有可用链接时,尝试获取链接的次数
			if(pr.getValue("checkTimes") != null){
				config.setCheckTimes(Integer.valueOf(pr.getValue("checkTimes")));
			}
			initPool();
		} catch (IOException e) {
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} catch (SQLException e) {
			e.printStackTrace();
		}

	}
	/**
	 * 隐藏构造函数
	 */
	private ConnectionPool(){
		
	}
	
	/**
	 * 初始化连接池 保存minConnections个链接
	 * @throws SQLException
	 * @throws ClassNotFoundException 
	 */
	private static synchronized void initPool() throws SQLException, ClassNotFoundException{
		conns = new Stack<Connection>();
		Class.forName(config.getDriver());
		for(int i = 0 ; i < config.getMinConnections() ; i++){
			Connection conn = newConnection();
			conns.push(conn);
		}
		initFlag = true;
	}
	/**
	 * 获取一个可用链接
	 * @return
	 * @throws SQLException 
	 * @throws InterruptedException 
	 * @throws DBPoolException 
	 * @throws Exception
	 */
	public static Connection getConn() throws SQLException, InterruptedException, DBPoolException  {
		Connection conn = null;
		if (initFlag) {
			synchronized (conns) {
				// 循环次数
				int times = 0;
				while (null == conn && times < config.getCheckTimes() + 1) {
					times++;
					// 如果未达到最大链接
					if (curConnections < config.getMaxConnections()) {
						// 栈中未空
						if (!conns.isEmpty()) {
							conn = conns.pop();
							// 如果返回的链接不可用
							if (null == conn || conn.isClosed()) {
								conn = newConnection();
							}
						// 栈中空了
						} else {
							conn = newConnection();
						}
					} else {
						conns.wait(config.getCheckoutTimeout());
					}

				}
				if(null == conn){
					logger.warn("获取链接超时!!!!!");
					throw new DBPoolException("获取链接超时!!!!!");
				}else{
					curConnections++;
					conns.notifyAll();
				}

			}
		} else {
			logger.error("连接池初始化失败!!!!");
			throw new DBPoolException("连接池初始化失败!!!!");
		}

		return conn;
	}
	
	/**
	 * 归还一个链接
	 * @param conn
	 * @throws SQLException
	 * @throws InterruptedException
	 */
	public static void returnConn(Connection conn) throws SQLException, InterruptedException {
		synchronized (conns) {
			if (null != conn && !conn.isClosed()) {
				// 如果设置归还前自动提交为真
				if (config.isAutoCommitOnClose()) {
					conn.commit();
				} else {
					conn.rollback();
				}
			}
			int times = 0;
			//尝试归还5次 如果归还失败则关闭连接
			while (times < 6) {
				times++;
				if (curConnections > 0 && curConnections <= config.getMaxConnections()) {
					conns.push(conn);
					curConnections--;
					break;
				} else if (curConnections == 0) {
					conns.wait(1000);
				} else {
					if(conn!=null && !conn.isClosed())
						conn.close();
					curConnections--;
					break;
				}
			}
			if(times == 5 && conn != null && !conn.isClosed()){
				conn.close();
			}
			
			
			conns.notifyAll();
		}
	}
	
	/**
	 * 简单的创建一个链接
	 * @return
	 * @throws SQLException
	 */
	private static Connection newConnection() throws SQLException{
		return DriverManager.getConnection(config.getUrl(),config.getUsername(),config.getPassword());
	}
	/**
	 * 获取已使用的连接数
	 * @return
	 */
	public static int getCurConnections() {
		return curConnections;
	}
		
}



Config.java
public class Config {
	private String driver;
	private String url;
	private String username;
	private String password;
	private int minConnections = 10;
	private int maxConnections = 20;
	private boolean autoCommitOnClose = true;
	private int checkoutTimeout = 100;
	private int checkTimes = 10;

	public String getDriver() {
		return driver;
	}

	public void setDriver(String driver) {
		this.driver = driver;
	}

	public String getUrl() {
		return url;
	}

	public void setUrl(String url) {
		this.url = url;
	}

	public String getUsername() {
		return username;
	}

	public void setUsername(String username) {
		this.username = username;
	}

	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	public int getMinConnections() {
		return minConnections;
	}

	public void setMinConnections(int minConnections) {
		this.minConnections = minConnections;
	}

	public int getMaxConnections() {
		return maxConnections;
	}

	public void setMaxConnections(int maxConnections) {
		this.maxConnections = maxConnections;
	}

	public boolean isAutoCommitOnClose() {
		return autoCommitOnClose;
	}

	public void setAutoCommitOnClose(boolean autoCommitOnClose) {
		this.autoCommitOnClose = autoCommitOnClose;
	}

	public int getCheckoutTimeout() {
		return checkoutTimeout;
	}

	public void setCheckoutTimeout(int checkoutTimeout) {
		this.checkoutTimeout = checkoutTimeout;
	}

	public int getCheckTimes() {
		return checkTimes;
	}

	public void setCheckTimes(int checkTimes) {
		this.checkTimes = checkTimes;
	}
	
	
}



PropertyReader.java
public class PropertyReader {
	Logger log = Logger.getLogger(PropertyReader.class);
	Properties props = null;
	public PropertyReader(String path) throws IOException{
		props = new Properties();
		try {
			props.load(getClass().getClassLoader().getResourceAsStream(path));
		} catch (IOException e) {
			log.error("读取properties失败");
			throw e;
		}
	}
	public String getValue(String key){
		return props.getProperty(key);
	}
}




DBPoolException .java
public class DBPoolException extends Throwable {
	public DBPoolException(String str){
		super(str);
	}
}



properties配置文件
driver=oracle.jdbc.driver.OracleDriver
url=jdbc:oracle:thin:@localhost:1521:orcl
username=test
password=password
minConnections=10
maxConnections=30
#当链接关闭的时候自动将未提交的内容提交
autoCommitOnClose=false
#当连接池用完时客户端调用getConn()后等待获取新连接的时间,Default: (100毫秒)
checkoutTimeout=100
#当没有可用链接时,尝试获取链接的次数
checkTimes=30
分享到:
评论
37 楼 rhythm_01 2011-03-21  
kimmking 写道
个人觉得,一个数据库连接池,必须是非侵入性的,和jdbc本身兼容。

即我只需要把jdbc/datasource配置改成连接池的设置,
原来用jdbc写的代码什么都不用改。

比如只换掉一个jdbc driver类。


2楼的意思应该就是实现DataSource,这样程序里使用时,或者说使用Hibernate、Spring来配置连接池时可以不用修改。

不过我觉得这个也是没必要的,真要是想用连接池可以使用第三方的,现在有很多成熟的,但是这种连接池的设计思路可以学习借签。
36 楼 xika.xiang 2011-03-15  
学习了原理,对连接池还还没深入过
35 楼 nianien 2011-03-15  
yy59750901 写道
/**
* 获取一个可用链接
* @return
* @throws SQLException
* @throws InterruptedException
* @throws DBPoolException
* @throws Exception
*/
public static Connection getConn() throws SQLException, InterruptedException, DBPoolException  {
Connection conn = null;
if (initFlag) {
synchronized (conns) {
// 循环次数
int times = 0;
while (null == conn && times < config.getCheckTimes() + 1) {
times++;
// 如果未达到最大链接
if (curConnections < config.getMaxConnections()) {
// 栈中未空
if (!conns.isEmpty()) {
conn = conns.pop();
// 如果返回的链接不可用
if (null == conn || conn.isClosed()) {
conn = newConnection();
}
// 栈中空了
} else {
conn = newConnection();
}
} else {
conns.wait(config.getCheckoutTimeout());
}

}
if(null == conn){
logger.warn("获取链接超时!!!!!");
throw new DBPoolException("获取链接超时!!!!!");
}else{
curConnections++;
conns.notifyAll();
}

}
} else {
logger.error("连接池初始化失败!!!!");
throw new DBPoolException("连接池初始化失败!!!!");
}

return conn;
}




你获取连接的逻辑不对吧?我之前也写过连接池,但是感觉很不靠谱,有些地方的实现需要挺复杂的技术来优化,说说我的几点看法吧:
第一,你的等待超时根本不是用时间来衡量的,你的getCheckTimes只不过一个计数器而已
第二,因为用的synchronized的关键字进行同步,那么等待超时就应该启动一个线程来监听,
否则的话,当多个请求同时到达的话,只能对一个请求计时,造成超长等待的问题
第三,对于从线程获取的数据库连接,你需要重写其close方法和isClosed()方法,以及其他依赖于close方法的方法
这里可以我觉得可以使用代理模式来实现
第四,释放数据库连接需要同步么?我觉得同步会造成不必要的阻塞,一般来说获取资源同步,释放资源我觉得不必要,因为我们每次取资源的时候会进行校验,当然也可能有其他的问题,只是我没想到
第五,是否需要一个监听进程来动态维护线程池的数量?总是当线程太满或者太空都是浪费资源
34 楼 ymkyve 2011-03-14  
javaso 写道
实现DataSource


头像把偶误导了,不过一语道破
33 楼 yy59750901 2011-03-14  
qqggcc 写道
<DBConfig>
<DB>
<id>HBSK</id>
<name>dbname</name>
<typeName>jtds</typeName>
<ip>192.168.0.16</ip>
<port>1433</port>
<user>sa</user>
<pwd>sa123</pwd>
</DB>
<DBConfig>

辛苦你了 我去研究一下
32 楼 wendal 2011-03-14  
没有复杂功能的连接池实现,都很快的.

以前一个简单的连接池实现,
http://myblog.sunfarms.net/243.html

真正的连接池,都是需要使用Connection/Statement/ResultSet接口等一系列接口的.
31 楼 qqggcc 2011-03-14  
<DBConfig>
<DB>
<id>HBSK</id>
<name>dbname</name>
<typeName>jtds</typeName>
<ip>192.168.0.16</ip>
<port>1433</port>
<user>sa</user>
<pwd>sa123</pwd>
</DB>
<DBConfig>
30 楼 qqggcc 2011-03-14  
package cn.xml;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamConstants;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import cn.databean.DataBase;
public class DBConfigReader {
ArrayList<DataBase> al=new ArrayList<DataBase>();
public ArrayList<DataBase> getList(){
return al;
}
public DBConfigReader(){
al.removeAll(al);
read(null);
}
public DBConfigReader(String file){
al.removeAll(al);
read(file);
}
  void read(String file) {
DataBase db = null;
int pos=0;
String NAME="";
String VALUE="";
XMLInputFactory factory = XMLInputFactory.newInstance();
Class c = cn.xml.DBConfigReader.class;
XMLStreamReader r = null;
String ss =c.getResource("../../").getPath()+"conf/db.xml";
if(null!=file&&!"".equals(file.trim()))
ss=file;
try {
InputStream input = new FileInputStream(new File(ss));
r = factory.createXMLStreamReader(input);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (XMLStreamException e1) {
e1.printStackTrace();
}

try {
int event = ((XMLStreamReader) r).getEventType();
while (true) {
switch (event) {
case XMLStreamConstants.START_DOCUMENT: {
pos++;
//System.out.println("Start Document.");
break;
}
case XMLStreamConstants.START_ELEMENT: {
VALUE="";
NAME=r.getName().toString();
if("DB".equalsIgnoreCase(NAME)){
pos++;
db=new DataBase();
}
//System.out.println("Start Element: " + r.getName());
//for (int i = 0, n = r.getAttributeCount(); i < n; ++i)
//System.out.println("Attribute: "+ r.getAttributeName(i) + "="+ r.getAttributeValue(i));
break;
}
case XMLStreamConstants.CHARACTERS: {
if (r.isWhiteSpace())
break;
if(pos==2){
VALUE=VALUE+r.getText();
}
//System.out.println("Text: " + r.getText());
break;
}
case XMLStreamConstants.END_ELEMENT: {
NAME=r.getName().toString();
if("DB".equalsIgnoreCase(NAME)){
al.add(db);
pos--;
}else if(pos==2){
if("IP".equalsIgnoreCase(NAME)){
db.setIp(VALUE);
}else if("id".equalsIgnoreCase(NAME)){
db.setId(VALUE);
}else if("PORT".equalsIgnoreCase(NAME)){
db.setPort(VALUE);
}else if("PWD".equalsIgnoreCase(NAME)){
db.setPwd(VALUE);
}else if("typeName".equalsIgnoreCase(NAME)){
db.setTypeName(VALUE);
}else if("user".equalsIgnoreCase(NAME)){
db.setUser(VALUE);
}else if("name".equalsIgnoreCase(NAME)){
db.setName(VALUE);
}

}
VALUE=null;
//System.out.println("End Element:" + r.getName());
break;
}
case XMLStreamConstants.END_DOCUMENT: {
//System.out.println("End Document.");
pos--;
break;
}
}
try {
if (!r.hasNext())
break;
event = r.next();
} catch (XMLStreamException e) {
e.printStackTrace();
}
}
} finally {
try {
r.close();
} catch (XMLStreamException e) {
e.printStackTrace();
}
}

}
public void save(){

}
public static void main(String[] arg){
DBConfigReader r=new DBConfigReader();
List l=r.getList();
int t=0;
t++;
}

}
29 楼 qqggcc 2011-03-14  
package cn.databean;
import java.io.File;
import java.sql.*;
import java.util.*;

import com.sun.rowset.CachedRowSetImpl;

import cn.task.Task;
import cn.task.TaskItem;
import cn.xml.DBConfigReader;
import cn.xml.TaskItemReader;
import cn.xml.TaskReader;
public class ParamMeta {
/***
* 数据库连接管理空间
*/

static List<TaskDO> l=null;
static List<TaskItemDO> il=null;
static Map<String,Connection> MCON=new  HashMap<String,Connection>();
/**
* 数据库配置管理空间
*/
static Map<String,DataBase> MDB=new  HashMap<String,DataBase>();

public static Connection getConById(String id){
Connection con=MCON.get(id);
try {
if(con==null||con.isClosed()){
createConnection(id);
}
} catch (Exception e) {
boolean created=false;
try {
while(con==null||con.isClosed()){
cn.util.Log.log("连接"+id+"失败,等待一分钟再试!","db");
Thread.sleep(1000*60);
con=null;
createConnection(id);
}
} catch (Exception e1) {
e1.printStackTrace();
}
e.printStackTrace();
}
con=MCON.get(id);
return con;
}

public static DataBase getDataBaseById(String id){
return MDB.get(id);
}
public static Map<String,DataBase> getMDB(){
return MDB;
}
/**
* 任务子项管理配置空间
*/
static Map<String,TaskItemDO> MTID=new  HashMap<String,TaskItemDO>();
public static TaskItemDO getTaskItemDOById(String id){
return MTID.get(id);
}
/**
* 任务子项管理空间
*/
static Map<String,TaskItem> MTI=new  HashMap<String,TaskItem>();
public static TaskItem getTaskItemById(String id){
return MTI.get(id);
}
/**
* 任务项配置管理空间
*/
static Map<String,TaskDO> MTD=new  HashMap<String,TaskDO>();
public static TaskDO getTaskDOById(String id){
return MTD.get(id);
}
/**
* 任务项管理空间
*/
static Map<String,Task> MT=new  HashMap<String,Task>();
public static Task getTaskById(String id){
return MT.get(id);
}
/**
* 结果集管理空间
*/
static Map<String,CachedRowSetImpl> MCRS=new  HashMap<String,CachedRowSetImpl>();
public static CachedRowSetImpl getCacheResultSetById(String id){
return MCRS.get(id);
}
public static void removeCacheResultSetById(String id){
MCRS.remove(id);
}
public static void setCacheResultSetById(String id,CachedRowSetImpl rs){
MCRS.put(id, rs);
}
/**
* 结果集管理空间
*/
static Map<String,ResultSet> MRS=new  HashMap<String,ResultSet>();
public static ResultSet getResultSetById(String id){
return MRS.get(id);
}
public static void removeResultSetById(String id){
MRS.remove(id);
}
public static void setResultSetById(String id,ResultSet rs){
MRS.put(id, rs);
}
/**
* XML文件管理空间
*/
static Map<String,File> MFXML=new  HashMap<String,File>();

/**
* XML文件管理空间
*/
static Map<String,Timer> MTIMER=new  HashMap<String,Timer>();
public static Timer getTimerById(String id){
return MTIMER.get(id);
}
public static void setTimerById(String id,Timer timer){
MTIMER.put(id, timer);
}
public static void removeTimerById(String id){
MTIMER.remove(id);
}


public static void initParam(){
initDataSourc();
initTaskItem();
initTask();
}
private static void initDataSourc(){
DBConfigReader r=new DBConfigReader();
List<DataBase> l=r.getList();
MDB.clear();
for(DataBase db: l){
MDB.put(db.getId(),db);

}
}
private static void initTaskItem(){
TaskItemReader r=new TaskItemReader();
List<TaskItemDO> il=r.getList();
MTID.clear();
for(TaskItemDO ti:il){
MTID.put(ti.getId(), ti);

}
}
private static void createConnection(String id){
MCON.put(id,getConnection(id));
}
public static Connection getConnection(String id){
DataBase db=getDataBaseById(id);
Connection con=null;
try {
Class.forName(db.getDriver());
con=java.sql.DriverManager.getConnection(db.getDburl(), db.getUser(),db.getPwd());
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
return con;
}
private static void initTask(){
TaskReader r=new TaskReader();
l=r.getList();
MTD.clear();
for(TaskDO t:l){
MTD.put(t.getId(), t);
//MT.put(t.getId(), new Task(t));
}
}
public static List<TaskDO> getTaskList(){
return l;
}
public static List<TaskItemDO> getTaskItemList(){
return il;
}
static {
initParam();
}

}
28 楼 qqggcc 2011-03-14  
package cn.databean;

public class DataBase {
String id="";
String name="";
String typeName="";
String port="";
String user="";
String ip="";
String pwd="";

public DataBase() {
}

public DataBase(String id, String name, String typeName, String port,
String user, String ip, String pwd) {
super();
this.id = id;
this.name = name;
this.typeName = typeName;
this.port = port;
this.user = user;
this.ip = ip;
this.pwd = pwd;
}
public String[] dbtypes = { "oracle", "ms sql", "mysql", "db2", "Sybase","jtds" };

private String[] dbdrivers = {
"oracle.jdbc.driver.OracleDriver",
"com.microsoft.jdbc.sqlserver.SQLServerDriver",
"org.gjt.mm.mysql.Driver",
"com.ibm.db2.jdbc.app.DB2Driver",
"com.sybase.jdbc.SybDriver",
"net.sourceforge.jtds.jdbc.Driver"
};

private String[] dburls = {
"jdbc:oracle:thin:@",
"jdbc:microsoft:sqlserver://",
"jdbc:mysql://",
"jdbc:db2://",
"jdbc:sybase:Tds:",
"jdbc:jtds:sqlserver://"
};

private String[] dbports = { "1521", "1433", "3306", "5000", "5007","1433" };

private int checktype(String adbtype) {
int check = -1;
for(int i=0;i<dbtypes.length;i++)
{ if(adbtype.equals(dbtypes[i]))
{
check=i;
break;
   }
}
return check;
}
public String getDriver() {
int index=checktype(this.typeName);
return dbdrivers[index];
}

public String getDburl() {
int index=checktype(this.typeName);
String dburl="";
switch(index){
case 0:{
dburl=dburls[index]+ip+":"+port+":"+name;
break;
}
case 1:{
dburl=dburls[index]+ip+":"+port+";DatabaseName="+name;
break;
}
case 2:{
dburl=dburls[index]+ip+"/"+name;
break;
}
case 3:{
dburl=dburls[index]+ip+":"+port+"/"+name;
break;
}
case 4:{
dburl=dburls[index]+ip+":"+port+"/"+name;
break;
}
case 5:{
dburl = dburls[index] + ip + ":" + port + "/" + name;
break;
}
}
return dburl;
}
public String getId() {
return id;
}

public void setId(String id) {
this.id = id;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public String getTypeName() {
return typeName;
}

public void setTypeName(String typeName) {
this.typeName = typeName;
}

public String getPort() {
return port;
}

public void setPort(String port) {
this.port = port;
}

public String getUser() {
return user;
}

public void setUser(String user) {
this.user = user;
}

public String getIp() {
return ip;
}

public void setIp(String ip) {
this.ip = ip;
}

public String getPwd() {
return pwd;
}

public void setPwd(String pwd) {
this.pwd = pwd;
}


}
27 楼 qqggcc 2011-03-14  
package cn.db;

import java.sql.Connection;
import java.sql.SQLException;
import java.util.LinkedList;
import java.util.List;
import cn.databean.DataBase;
import cn.databean.ParamMeta;

public class ConnectionWrapper extends java.util.TimerTask {
static int min = 2, max = 15;
String id;
private LinkedList conLL = null;
private java.util.LinkedList useableLL = null;
private java.util.LinkedList usingLL = null;
static ConnectionWrapper cw = null;
java.util.Date lastDate = new java.util.Date();
DataBase db = null;


private ConnectionWrapper(int min, int max,String id) {
this.id=id;
db = ParamMeta.getDataBaseById(id);
conLL = new java.util.LinkedList();
useableLL = new java.util.LinkedList();
usingLL = new java.util.LinkedList();
}

public static ConnectionWrapper getInstance(String id) {
cw = new ConnectionWrapper(min, max,id);
java.util.Timer t = new java.util.Timer();
t.schedule(cw, new java.util.Date(), 10000);
return cw;
}

public synchronized Connection getConnection() {
Connection con = null;
while (true) {
if (useableLL.size() > 0) {
con = (Connection) useableLL.getFirst();
useableLL.removeFirst();
usingLL.add(con);
break;
} else {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
return con;
}

public synchronized void close(Connection con) {
try {
if (con != null && !con.isClosed()) {
usingLL.remove(con);
useableLL.add(con);
// System.out.println("共有" + conLL.size() + "个连接,可用的为" +
// useableLL.size() + ",正在使用的为" + usingLL.size());
}
} catch (SQLException e) {
e.printStackTrace();
usingLL.remove(con);
conLL.remove(con);
}

}

public void run() {
if ((float) usingLL.size() / (float) conLL.size() < 0.4) {
if (((new java.util.Date()).getTime() - lastDate.getTime()) > 5 * 60 * 1000) {
batchClose((int) ((max - min) * (1 - (float) usingLL.size()
/ (float) conLL.size())));
}
} else {
lastDate = new java.util.Date();
}

if (conLL.size() > 0) {
while (useableLL.size() < 2 && conLL.size() < max) {
batchCreate(5);
}
} else {
batchCreate(min);
}

}

private void batchClose(int count) {
// System.out.println("自动关闭连接前共有"+ conLL.size() + "个连接,可用的为" +
// useableLL.size() + ",正在使用的为" + usingLL.size());
Connection con = null;
for (int i = 0; i < count; i++) {
if (useableLL.size() > min) {
con = (Connection) useableLL.getLast();
useableLL.remove(con);
conLL.remove(con);
try {
con.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
// System.out.println("自动关闭后连接前共有"+ conLL.size() + "个连接,可用的为" +
// useableLL.size() + ",正在使用的为" + usingLL.size());
}

private void batchCreate(int count) {
for (int i = 0; i < count; i++) {
Connection con = createConnection(db);
try {
if (con != null && !con.isClosed()) {
conLL.add(con);
useableLL.add(con);
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}

private static Connection createConnection(DataBase db) {
try {
Class.forName(db.getDriver());
Connection con = java.sql.DriverManager.getConnection(db.getDburl(), db.getUser(), db.getPwd());
return con;
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
return null;
}
}
26 楼 qingwaxw1980 2011-03-14  
wing5jface 写道
如果使用的某一个数据库连接未归还,超过一定时间,没有相关的线程代码监控?

这样的连接池,不能算是成熟产品,小规模应用而已。
25 楼 href 2011-03-14  
请问 initPool();用synchronized 有这个必要吗?在static中,还怕并发?
24 楼 kimmking 2011-03-14  
connection用proxy也是个好办法。直接delegate也可以。
23 楼 yuanxd 2011-03-13  
连接池应该可以配置多个数据源,根据数据源的名称来获取一个数据库的链接。
还有归还connection最好用代理来实现,直接调用conn.close()来归还,这样用起来代码不需要改动。
上周自己写了一个java连接池,所以讲点看法,本人也是菜鸟。。。
22 楼 yy59750901 2011-03-13  
kimmking 写道
wendal 写道
连接池其中一个很重要的功能: 返回连接前,设置autocommit的值.

bonecp 0.7.1之前的版本就没考虑这一点.

正解,jdbc拿到一个connection时,默认的参数应该复位,比如
autocommit为true

看你刚才那一堆后台log 真专业。。。
嘿嘿 这些东西跟大家探讨一下能想到很多  比我自己瞎琢磨强多了
21 楼 kimmking 2011-03-13  
wendal 写道
连接池其中一个很重要的功能: 返回连接前,设置autocommit的值.

bonecp 0.7.1之前的版本就没考虑这一点.

正解,jdbc拿到一个connection时,默认的参数应该复位,比如
autocommit为true
20 楼 wendal 2011-03-13  
连接池其中一个很重要的功能: 返回连接前,设置autocommit的值.

bonecp 0.7.1之前的版本就没考虑这一点.
19 楼 wendal 2011-03-13  
实现DataSource接口就好了.
18 楼 kimmking 2011-03-13  
13个并发线程竞争9个资源。

      ********      ====>   delete database.
      ********      ====>   init DataSource and create database.
main->request connection at 1299985865796
main->create new connection...list.size()=0 this.maxPoolSize=10
      ********      ====>   create table.
      ********      ====>   ********** start TEST threads.
test0->request connection at 1299985873546
test1->request connection at 1299985873546
test2->request connection at 1299985873546
test3->request connection at 1299985873546
test4->request connection at 1299985873546
test5->request connection at 1299985873546
test0->create new connection...list.size()=1 this.maxPoolSize=10
test7->request connection at 1299985873546
test6->request connection at 1299985873546
test9->request connection at 1299985873546
test8->request connection at 1299985873546
test12->request connection at 1299985873546
test11->request connection at 1299985873546
test10->request connection at 1299985873546
test10->create new connection...list.size()=2 this.maxPoolSize=10
test11->create new connection...list.size()=3 this.maxPoolSize=10
test12->create new connection...list.size()=4 this.maxPoolSize=10
test8->create new connection...list.size()=5 this.maxPoolSize=10
test9->create new connection...list.size()=6 this.maxPoolSize=10
test6->create new connection...list.size()=7 this.maxPoolSize=10
test7->create new connection...list.size()=8 this.maxPoolSize=10
test5->create new connection...list.size()=9 this.maxPoolSize=10
test2->All connectios is busy, waiting for 50ms, 10
test3->All connectios is busy, waiting for 50ms, 10
test1->All connectios is busy, waiting for 50ms, 10
test4->All connectios is busy, waiting for 50ms, 10
test2->94,1000
test1->94,1000
test2->Iterator for connection...list.size()=10 this.maxPoolSize=10
test3->94,1000
test3->Iterator for connection...list.size()=10 this.maxPoolSize=10
test4->94,1000
test1->Iterator for connection...list.size()=10 this.maxPoolSize=10
test4->Iterator for connection...list.size()=10 this.maxPoolSize=10
test4->All connectios is busy, waiting for 50ms, 10
test2->All connectios is busy, waiting for 50ms, 10
test3->All connectios is busy, waiting for 50ms, 10
test1->All connectios is busy, waiting for 50ms, 10
test4->157,1000
test1->157,1000
test1->Iterator for connection...list.size()=10 this.maxPoolSize=10
test1->All connectios is busy, waiting for 50ms, 10
test3->157,1000
test2->157,1000
test2->Iterator for connection...list.size()=10 this.maxPoolSize=10
test2->All connectios is busy, waiting for 50ms, 10
test3->Iterator for connection...list.size()=10 this.maxPoolSize=10
test3->All connectios is busy, waiting for 50ms, 10
test4->Iterator for connection...list.size()=10 this.maxPoolSize=10
test4->All connectios is busy, waiting for 50ms, 10
test2->219,1000
test4->219,1000
test3->219,1000
test1->219,1000
test1->Iterator for connection...list.size()=10 this.maxPoolSize=10
test3->Iterator for connection...list.size()=10 this.maxPoolSize=10
test4->Iterator for connection...list.size()=10 this.maxPoolSize=10
test2->Iterator for connection...list.size()=10 this.maxPoolSize=10
test4->All connectios is busy, waiting for 50ms, 10
test3->All connectios is busy, waiting for 50ms, 10
test1->All connectios is busy, waiting for 50ms, 10
test2->All connectios is busy, waiting for 50ms, 10
test1->282,1000
test1->Iterator for connection...list.size()=10 this.maxPoolSize=10
test4->282,1000
test1->All connectios is busy, waiting for 50ms, 10
test2->282,1000
test2->Iterator for connection...list.size()=10 this.maxPoolSize=10
test3->282,1000
test2->All connectios is busy, waiting for 50ms, 10
test4->Iterator for connection...list.size()=10 this.maxPoolSize=10
test4->All connectios is busy, waiting for 50ms, 10
test3->Iterator for connection...list.size()=10 this.maxPoolSize=10
test3->All connectios is busy, waiting for 50ms, 10
org.qsoft.qpool.QpoolConnection@1bc16f0 to free.
test5  ==>  done. spend time: 313
org.qsoft.qpool.QpoolConnection@18622f3 to free.
test8  ==>  done. spend time: 313
org.qsoft.qpool.QpoolConnection@92dcdb to free.
org.qsoft.qpool.QpoolConnection@5eb489 to free.
org.qsoft.qpool.QpoolConnection@160877b to free.
test12  ==>  done. spend time: 313
test6  ==>  done. spend time: 313
org.qsoft.qpool.QpoolConnection@3a1ec6 to free.
org.qsoft.qpool.QpoolConnection@1a6684f to free.
org.qsoft.qpool.QpoolConnection@1e1be92 to free.
org.qsoft.qpool.QpoolConnection@1e1be92 to free.
test0  ==>  done. spend time: 313
test9  ==>  done. spend time: 313
test11  ==>  done. spend time: 313
test10  ==>  done. spend time: 313
test7  ==>  done. spend time: 313
test1->344,1000
test1->Iterator for connection...list.size()=10 this.maxPoolSize=10
test3->344,1000
test2->344,1000
test4->344,1000
test2->Iterator for connection...list.size()=10 this.maxPoolSize=10
test3->Iterator for connection...list.size()=10 this.maxPoolSize=10
test1->get free connection:org.qsoft.qpool.QpoolConnection@1e1be92
test4->Iterator for connection...list.size()=10 this.maxPoolSize=10
test3->get free connection:org.qsoft.qpool.QpoolConnection@160877b
test4->get free connection:org.qsoft.qpool.QpoolConnection@3a1ec6
test2->get free connection:org.qsoft.qpool.QpoolConnection@5eb489
org.qsoft.qpool.QpoolConnection@3a1ec6 to free.
test4  ==>  done. spend time: 360
org.qsoft.qpool.QpoolConnection@160877b to free.
test3  ==>  done. spend time: 360
org.qsoft.qpool.QpoolConnection@5eb489 to free.
test2  ==>  done. spend time: 360
org.qsoft.qpool.QpoolConnection@1e1be92 to free.
test1  ==>  done. spend time: 360
      ********      ====>   count = 26
org.qsoft.qpool.QpoolConnection@1c7980c to free.

相关推荐

    易语言NetDB数据库操作中间件

    2、**本次更新的数据库池支持现在设定的多个数据库同时在线。 3、**优化链接数据库速度提升。 ================ [2020-1-5日] ================ 1、**修正服务端连续读数据时崩溃问题,感谢群友(无极)帮忙测试,...

    设计模式_简单易懂的例子,且很有意思

    当应用程序需要确保某些资源只被创建一次时,比如数据库连接池、日志对象等,可以使用单例模式。 **实现细节**: 单例模式可以通过构造器私有化、静态内部类等方式实现。 #### 四、多例模式 **定义**: 多例模式...

    MINA/JAVA游戏服务端源码

    db.jdbc:jdbc连接池 game:开始游戏 game.message:消息管理者,将客户端的消息传到具体的处理器处理 game.message.handler:消息处理者(功能实现的地方,上接service,下连DAO) net.mina.protocol:自定义通信...

    Java设计模式经典搞笑珍藏版

    这种模式常用于创建数据库连接池、线程池等共享资源。 #### 五、多例模式(Multiton Pattern) 多例模式是单例模式的一种变体,允许根据不同的参数返回不同的实例。这通常用于需要根据某种条件创建不同实例的情况。...

    java24种设计模式介绍与6大设计原则

    这种模式常用于日志记录、数据库连接池、线程池等场景,以避免资源浪费和提高性能。 ##### 4. **多例模式【Multiton Pattern】** 多例模式是单例模式的一个变体,它允许一个类有多个实例,并且可以根据某种标识...

    java设计模式

    - **应用场景**:数据库连接池、日志对象等。 - **多例模式(Multiton Pattern)** - **定义**:与单例模式类似,但允许有多个实例。 - **应用场景**:用户设置等,每个用户可以有自己的配置。 - **抽象工厂模式...

    C++设计模式

    在很多情况下,我们希望整个系统中只有一个特定的对象存在,例如数据库连接池、线程池等。此时,单例模式就能派上用场。 #### 实现 实现一个简单的单例类: ```cpp class Singleton { private: static Singleton...

    Java设计模式面试实用

    **案例**:假设需要创建一个数据源管理器的多例,根据不同的数据库名称创建对应的连接池。 ```java import java.util.HashMap; import java.util.Map; public class DataSourceManager { private static final ...

    java设计模式1

    在多线程环境中,我们需要确保某些资源只能被一个线程访问,例如数据库连接池、日志记录器等。 1. **懒汉式单例模式**: ```java public class Singleton { private static Singleton instance; private ...

Global site tag (gtag.js) - Google Analytics