`
zeroliu
  • 浏览: 193585 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

重新实现的db4o连接池

阅读更多
【虎.无名】看了Roson的db4o连接池实现,似乎存在一些问题:
1,使用sleep或者wait/notify是为了避免循环忙等待,这个非常消耗CPU资源,否则不适合用于生产环境。
2,限制在Jdk1.5以上版本了,并非必要。
3,用户应该可以选择本地模式,还是远程模式;对于后者,需要远程服务器和端口,同时,在代码上,就无需Db4o.openServer了。
于是乎,一时手痒,就重新实现了一个,看看测试效果,虽然达到了互斥,但是db4o内部似乎还存在一些问题。set进去的类,没有成功保存,奇怪中。
/**  
 * Created on 2006-11-24 
 * @author liusheng (nike.lius@gmail.com)
 * @function 针对db4o的连接池管理,
 * @link file:///D:/OSS/db4o-5.5/doc/tutorial/index.html
 * DONE 参考了Rosen的ConnectionPool实现,并加以改进,Blog主页如下;
 * @link http://www.blogjava.net/rosen/category/13739.html
 * DONE 采用setter依赖注入方式,兼容Spring框架;
 * DONE 完成Poll拉模式连接池;db4o_pool中只存放空闲连接;
 * DONE 在main()中使用多线程测试,
 * TODO 在多线程中,set()后无效,已经commit了,奇怪。
*/
public class Db4oPool implements Db4oPoolInf {
	protected static Log _log = LogFactory.getLog(Db4oPool.class);
	//-------------------------------------
	private	int		_minSize = 1;	//允许的空闲连接;
	private	int 	_maxSize = 2;	
	public void setMinSize(int n) { _minSize = n; }
	public void setMaxSize(int n) { _maxSize = n; }
	public int getMinSize() 	{ return _minSize;	}
	public int getMaxSize() 	{ return _maxSize;	}
	
	private String	_file = null;
	private String	_host = null;
	private int		_port = 0;
	private String	_usr = null;
	private String	_pwd = null;
	
	public void set_file(String file) {	_file = file; }
	public void set_host(String host) {	_host = host; }
	public void set_port(int	port) {	_port = port; }
	public void set_usr(String s)	{	_usr = s; }
	public void set_pwd(String s)	{	_pwd = s; }
	//-------------------------------------
	private	ObjectServer	db4o_server = null;	//only for local
	private	List			db4o_pool = null;	//只存放空闲连接
	private	String			db4o_mode = null;
	private	int				db4o_count = 0;	//当前连接数
	//-------------------------------------
	public Db4oPool() {}		//需要调用set方法;
	public Db4oPool(String file) {
		set_file(file);		//Embedded模式
		db4o_mode = "embedded";
	}
	public Db4oPool(String host, int port, String usr, String pwd) {
		set_host(host);		//Client模式
		set_port(port);
		set_usr(usr);
		set_pwd(pwd);
		db4o_mode = "remote";
	}	
	//-------------------------------------
	public void start() throws Exception {
		synchronized(this){
			if (db4o_pool!=null)	return;
			db4o_pool = Collections.synchronizedList(new LinkedList());
			if (_file!=null) 	{	//对于embedded模式,打开本地库
				db4o_server = Db4o.openServer(_file, _port);
				_log.debug("# openServer("+_port+")..."+_file);
				if (_port>0 && _usr!=null && _pwd!=null) {
					db4o_server.grantAccess(_usr,_pwd);	//授权
					_log.debug("# grantAccess("+_usr+")...ok");
				}
			}		
			for(int i=0; i<this._maxSize; i++){	//打开多个数据库连接,尝试最大连接数
				ObjectContainer oc = this.m_open();
				db4o_pool.add(oc);
			}
			_log.debug("# start()...ok/"+db4o_pool.size());
		}
	}
	public void stop() {
		synchronized(this){
			for(Iterator i=db4o_pool.iterator(); i.hasNext(); ) {
				ObjectContainer oc = (ObjectContainer)i.next();
				oc.close();
			}		
			db4o_pool.clear();	
			db4o_pool = null;//全部清除		
			if (db4o_server!=null) {
				_log.debug("* close()...server");
				db4o_server.close();
				db4o_server = null;
			}
			_log.debug("* stop()...ok/"+db4o_mode);
		}
		
	}
	protected ObjectContainer m_open() throws IOException {
		ObjectContainer oc = null;
		if (db4o_server!=null) {	//已经打开
			oc = db4o_server.openClient();
			db4o_count++;
		}else if (_host!=null && _usr!=null && _pwd!=null) {
			oc = Db4o.openClient(_host, _port, _usr, _pwd);
			db4o_count++;
		}else {
			throw new IllegalArgumentException("need to set host,port,usr,pwd"); 
		}
		_log.debug("# m_open()..."+oc);
		return oc;
	}
	protected void m_close(ObjectContainer oc) {
		oc.close();		db4o_count--;
		_log.debug("* m_close()..."+oc);
	}
	protected void m_commit(ObjectContainer oc) {
		oc.commit();	//确保完成最后修改部分;
		_log.debug("* m_commit()..."+oc);
	}
	//-------------------------------------
	public synchronized ObjectContainer getConnection() throws Exception {
		if (db4o_pool==null) {
			throw new RuntimeException("(db4o_pool==null)");
		}
		while(db4o_pool.size()==0 && db4o_count>=_maxSize) {
			_log.warn("getConnection()...wait/size=0,count="+db4o_count);
			wait(1000);
		}
		ObjectContainer oc = null;
		if (db4o_pool.size()>0) {	//db4o_count<_maxSize
			Object obj = db4o_pool.remove(0);
			oc = (ObjectContainer)obj;
		}else {
			oc = m_open();
		}
		return oc;
	}
	public synchronized void closeConnection(ObjectContainer oc) {
		this.m_commit(oc);			//保险起见;
		if (db4o_pool.size() < this._minSize) {
			db4o_pool.add(oc);	//添加到连接池中;
			_log.debug("# closeConnection()...pooled 池化");
		}else {
			m_close(oc);		//直接释放
			_log.debug("# closeConnection()...closed 释放");
		}		
		notify();
	}
	//-------------------------------------
	static Random RAND = new Random(113);
	static class TJob extends Thread {
		Db4oPoolInf _pool = null;
		
		public TJob(Db4oPoolInf pool) {
			_pool = pool;
		}
		public void run() {
			ObjectContainer oc = null;
			try {
				oc = _pool.getConnection();//释放
				oc.set("Hello "+this.getName());
				oc.commit();	//奇怪,没有设置进去?? # run()...q:0
				ObjectSet os = oc.query(String.class);
				_log.debug("# run()...q:"+os.size());
				Util.sleepMSec(RAND.nextInt(500)+500);	//随机等待一定时间,模拟实际操作
				_log.debug("# run()...end");
			}catch(Exception e){
				e.printStackTrace();
			}finally{
				_pool.closeConnection(oc);	//释放
			}			
		}
	}
	public static void main(String[] args) throws IOException {
		Util.configureClassPath("res/log4j.properties");
		Db4oPool pool = new Db4oPool("db4o/pool/Db4oPool.yap");
		try {
			pool.setMinSize(3);
			pool.setMaxSize(5);
			pool.set_port(8888);	//可选,运行外部访问;
			pool.set_usr("USER");	//可选
			pool.set_pwd("PASS");	//可选
			pool.start();
			//多线程测试
			Thread[] tt = new Thread[20];
			for(int i=0; i<tt.length; i++) {
				tt[i] = new TJob(pool);
				tt[i].start();
			}
			_log.debug("------- wait for join ------");
			for(int i=0; i<tt.length; i++) {
				tt[i].join();
			}
		}catch(Exception e) {
			e.printStackTrace();
		}finally{
			pool.stop();
		}
		_log.debug("--------- END -------");
	}
}
需要的辅助类如下,用于配置log4j以及随机等待。
class Util {
	protected static Log _log = LogFactory.getLog(Util.class);
	public static void configureClassPath(String cfg) throws IOException {
    	//格式: com/bs2/core/my.properties
        InputStream is = ClassLoader.getSystemClassLoader().getResourceAsStream(cfg);
        if (is==null)	throw new IOException("Not Found in ClassPath:"+cfg);
        Properties props = new Properties();
        try { props.load(is); }finally{ is.close(); }
        PropertyConfigurator.configure(props);
        _log.debug("# configureClassPath()..."+cfg);
    }
	public static void sleepMSec(int msec) {
		try {
			_log.debug("# sleepMSec("+msec+")...");
			Thread.sleep(msec);
		} catch (InterruptedException e) {
			// 忽略
		}
	}	
}
分享到:
评论
2 楼 zeroliu 2007-01-19  
这种连接池方式被否决了。两个问题:性能、有状态!

A:虎无名还在不在? 很重要的事情,大家还知道他的 blog 地址吗?
A:找到了 db4o team 正在开会,讨论到这个问题了。 
B:什么问题?String等简单类型不能直接保存的问题?
A:不是,在研究 C/S 性能问题。

A:无名在不在? 老外否定了我们辛辛苦苦拉扯大的 con pool , 原因是:每个 session 都是有状态的
B:是不是,还有信息缓存在con中,为了提供效率;
A:yes
B:conn与session相关性很强,而不象jdbc中conn,statement,等多级别的;
A:但是,C/S 模式下,性能的确不高。 看来 db4o 的确不是为 web app 开发的。
A:我觉得 web app 下肯定要 c/s 模式,要不多线程就 lock 了 
B:大概明白了,先吃饭去;)连接池已经有锁了呀,关键是,不知道它的这些状态信息,保存多久;
A:我是说,如果为了效率而使用嵌入式模式,在 web app 下肯定要 lock 数据库文件。
A:ok
1 楼 zeroliu 2006-12-06  
后来经过测试,db4o似乎不能设置简单类型(String,Integer等),而只能是集合类型,或者自定义Bean。这似乎是db4o刻意为之。把上述源代码种的 oc.set("Hello "+this.getName());  
改为:oc.set(new HashMap()); 就可以了。

相关推荐

    Db4o的简单操作项目

    http://www.db4o.com db4o的官网,可下载最新版本,jar包在项目的database目录下,若构建路径报错请重新添加

    对象数据库db4o对象数据库db4o

    对象数据库db4o的示例程序,对象数据库db4o, 对象数据库db4o

    db4o使用指南

    描述了db4o的信息要点和使用指南,讲述了一些特殊类,及其基本的使用

    db4o8.0以及db4o中文指南

    db4o8.0以及db4o中文操作指南

    db4o中文指南

    db4o 是一个开源的纯面向对象数据库引擎,对于 Java 与 .NET 开发者来说都是一个简单易用的对象持久化工具,使用简单。同时,db4o 已经被第三方验证为具有优秀性能的面向对象数据库, 下面的基准测试图对 db4o 和...

    db4o .net3.5

    db4o ,net db4o ,net db4o ,net db4o ,net

    DB4O-6.0

    For the fastest start with db4o please work through the tutorial, available in different formats in the following folder: ./doc/tutorial/ If you are working with db4o for Java, it is recommended...

    db4o .net2.0

    db4o .net2.0 db4o .net2.0db4o .net2.0 db4o .net2.0db4o .net2.0

    DB4O管理工具

    可以查看、删除DB4O数据库中的数据,支持*.yap、*.db、*.data等DB4O数据库

    DB4O笔记+常用JAR包

    DB4O 笔记+常用 JAR包 DB4O 笔记+常用 JAR包 DB4O 笔记+常用 JAR包 DB4O 笔记+常用 JAR包 DB4O 笔记+常用 JAR包

    db4o-8.0-java

    db4o最后发布的版本,包含全部源码、jar包,eclipse下的对象查看插件、全部说明文档等。

    开源面向对象数据库 db4o 之旅

    该资源为 db4o 之旅 系列文章: 1.介绍了面向对象数据库 db4o 的基本特性,并且与传统关系型数据库以及 OR 映射技术做了比较分析,读者可以体验到 db4o 的全新的面向对象存储的理念,并且给出了性能测试数据。 2....

    DB4O 说明文档

    DB4O 介绍信息.有兴趣的可以看看,了解一下.

    非常好的Db4o资料,适合想研究Db4o的同学

    非常好的Db4o资料,包括Db4o的七章内容详细介绍及相关的论文。

    《DB4O系统应用之起步篇》

    《DB4O系统应用之起步篇》.《DB4O系统应用之起步篇》.《DB4O系统应用之起步篇》.

    DB4O 8.0 Object Manager Enterprise

    DB4O 8.0 Object Manager Enterprise 对象浏览器,db4o-8.0-tutorial.pdf

    db4o 权威指南

    db4o 权威指南 pdf 非常好

    db4o开发指南和各种实例

    本资料转自网上,仅供学习DB4O开发教程使用

    db4o的ppt讲稿

    db4o 是一款开放源码对象导向数据库,能使 Java 和 .NET 开发人员不但大幅减低开发时间和成本, 同时能带来前所未有的效能. 另外, db4o 独有的对象导向数据库引擎能应用于免数据库管理人的流动装置或桌面平台, 套装...

    意想不到的数据库(DB4O)

    描述了DB4O的基础知识,同时其中还包含有更多的DB4O复制系统信息的链接地址.

Global site tag (gtag.js) - Google Analytics