`
zeroliu
  • 浏览: 197316 次
  • 性别: 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()); 就可以了。

相关推荐

    Redis操作基础文档

    5. **对象数据库**:如db4o、Versant等,直接存储面向对象编程语言中的对象,无需转换。 6. **XML数据库**:如Berkeley DB XML、BaseX等,专为XML数据设计,支持XQuery/XPath等查询语言。 #### 六、总结 Redis作为...

    【光子晶体】基于matlab FDTD模拟一维光子晶体中光波传输【含Matlab源码 11059期】.mp4

    海神之光上传的视频是由对应的完整代码运行得来的,完整代码皆可运行,亲测可用,适合小白; 1、从视频里可见完整代码的内容 主函数:main.m; 调用函数:其他m文件;无需运行 运行结果效果图; 2、代码运行版本 Matlab 2019b;若运行有误,根据提示修改;若不会,私信博主; 3、运行操作步骤 步骤一:将所有文件放到Matlab的当前文件夹中; 步骤二:双击打开main.m文件; 步骤三:点击运行,等程序运行完得到结果; 4、仿真咨询 如需其他服务,可私信博主; 4.1 博客或资源的完整代码提供 4.2 期刊或参考文献复现 4.3 Matlab程序定制 4.4 科研合作

    【海洋】基于matlab海洋卫星测高数据仿真DEM信息【含Matlab源码 10984期】.mp4

    海神之光上传的视频是由对应的完整代码运行得来的,完整代码皆可运行,亲测可用,适合小白; 1、从视频里可见完整代码的内容 主函数:main.m; 调用函数:其他m文件;无需运行 运行结果效果图; 2、代码运行版本 Matlab 2019b;若运行有误,根据提示修改;若不会,私信博主; 3、运行操作步骤 步骤一:将所有文件放到Matlab的当前文件夹中; 步骤二:双击打开main.m文件; 步骤三:点击运行,等程序运行完得到结果; 4、仿真咨询 如需其他服务,可私信博主; 4.1 博客或资源的完整代码提供 4.2 期刊或参考文献复现 4.3 Matlab程序定制 4.4 科研合作

    【光学】基于matlab蒙特卡洛方法求解辐射传输方程【含Matlab源码 10968期】.mp4

    海神之光上传的视频是由对应的完整代码运行得来的,完整代码皆可运行,亲测可用,适合小白; 1、从视频里可见完整代码的内容 主函数:main.m; 调用函数:其他m文件;无需运行 运行结果效果图; 2、代码运行版本 Matlab 2019b;若运行有误,根据提示修改;若不会,私信博主; 3、运行操作步骤 步骤一:将所有文件放到Matlab的当前文件夹中; 步骤二:双击打开main.m文件; 步骤三:点击运行,等程序运行完得到结果; 4、仿真咨询 如需其他服务,可私信博主; 4.1 博客或资源的完整代码提供 4.2 期刊或参考文献复现 4.3 Matlab程序定制 4.4 科研合作

    log凑字数 12345678910

    log凑字数 12345678910

    【毕业设计】java+springboot+vue电影评论网站系统设计与实现(完整前后端+mysql+说明文档+LunW).zip

    【毕业设计】java+springboot+vue电影评论网站系统设计与实现(完整前后端+mysql+说明文档+LunW).zip

    【图像分割】基于matlab方差标准四叉树分解图像分割【含Matlab源码 9827期】.mp4

    海神之光上传的视频是由对应的完整代码运行得来的,完整代码皆可运行,亲测可用,适合小白; 1、从视频里可见完整代码的内容 主函数:main.m; 调用函数:其他m文件;无需运行 运行结果效果图; 2、代码运行版本 Matlab 2019b;若运行有误,根据提示修改;若不会,私信博主; 3、运行操作步骤 步骤一:将所有文件放到Matlab的当前文件夹中; 步骤二:双击打开main.m文件; 步骤三:点击运行,等程序运行完得到结果; 4、仿真咨询 如需其他服务,可私信博主; 4.1 博客或资源的完整代码提供 4.2 期刊或参考文献复现 4.3 Matlab程序定制 4.4 科研合作

    双向全桥LLC谐振变换器与非对称拓扑的双向模型仿真研究:正向LLC与反向LC的变频控制闭环模型在Matlab Simulink及PLECS环境下的应用,双向全桥LLC谐振变换器:非对称拓扑与双向模型的

    双向全桥LLC谐振变换器与非对称拓扑的双向模型仿真研究:正向LLC与反向LC的变频控制闭环模型在Matlab Simulink及PLECS环境下的应用,双向全桥LLC谐振变换器:非对称拓扑与双向模型的Matlab Simulink及PLECS仿真研究,双向全桥LLC谐振变器仿真,非对称拓扑,双向模型 正向LLC,反向LC 采用变频控制的闭环模型 运行环境包括matlab simulink,plecs等 ~ ,双向全桥LLC谐振变换器仿真; 非对称拓扑; 双向模型; 变频控制; Matlab Simulink; PLECS。,双向全桥LLC谐振变换器仿真研究:非对称拓扑与变频控制模型

    Jordan标准型行列互逆方法-程序求解

    Jordan标准型行列互逆方法-程序求解

    DIN-SQL:分解式上下文学习的文本到SQL转换及自校正

    目前,在复杂任务(如Spider数据集上的文本到SQL转换)中,使用大型语言模型(LLMs)的微调模型和提示方法之间存在显著差距。为了提高LLMs在推理过程中的性能,我们研究了将任务分解为较小子任务的有效性。特别是,我们展示了将生成问题分解为子问题,并将这些子问题的解决方案输入给LLMs,可以显著提高其性能。我们的实验表明,这种方法使三个LLMs的简单少样本性能提高了大约10%,使其准确性接近或超过最先进水平(SOTA)。在Spider数据集的保留测试集中,以执行准确率为衡量标准,最先进水平是79.9,而使用我们方法的新最先进水平为85.3。我们的方法在上下文中学习,比许多经过深度微调的模型高出至少5%。此外,在BIRD基准测试中,我们的方法实现了55.9%的执行准确率,创下了该基准测试保留测试集的新最先进水平

    MATLAB-GUI-平台的手势识别.zip

    程序可以参考,非常好的思路建设,完美!

    【语音编码】基于matlab语音信号PCM编解码(含前后波形对比 SNR)【含Matlab源码 11159期】.mp4

    海神之光上传的视频是由对应的完整代码运行得来的,完整代码皆可运行,亲测可用,适合小白; 1、从视频里可见完整代码的内容 主函数:main.m; 调用函数:其他m文件;无需运行 运行结果效果图; 2、代码运行版本 Matlab 2019b;若运行有误,根据提示修改;若不会,私信博主; 3、运行操作步骤 步骤一:将所有文件放到Matlab的当前文件夹中; 步骤二:双击打开main.m文件; 步骤三:点击运行,等程序运行完得到结果; 4、仿真咨询 如需其他服务,可私信博主; 4.1 博客或资源的完整代码提供 4.2 期刊或参考文献复现 4.3 Matlab程序定制 4.4 科研合作

    (源码)基于FreeRTOS的ARM926EJS实验系统_2.zip

    # 基于FreeRTOS的ARM926EJS实验系统 ## 项目简介 本项目将FreeRTOS移植到基于ARM926EJ S CPU的ARM Versatile Platform Baseboard上,当前版本基于FreeRTOS 10.4.0,后续会随FreeRTOS新版本发布而更新。项目处于早期开发阶段,包含基础的演示任务,可用于学习和研究实时操作系统的基本功能与应用。 ## 项目的主要特性和功能 1. FreeRTOS内核移植实现FreeRTOS内核在ARM926EJ S架构上的移植,支持任务管理、信号量、队列、事件标志、互斥量等功能。 2. 中断处理具备中断服务例行程序,能处理中断事件并切换任务。 3. 任务切换有任务切换机制,支持手动切换和定时器中断切换。 4. 定时器管理可进行定时器的创建、启动、停止、查询等操作。 5. 内存管理实现动态内存分配与释放,支持运行时动态操作。

    【图像加密解密】基于matlab混沌系统和DNA编码图像分块加密解密(含直方图 密钥 相关性)【含Matlab源码 9695期】.mp4

    海神之光上传的视频是由对应的完整代码运行得来的,完整代码皆可运行,亲测可用,适合小白; 1、从视频里可见完整代码的内容 主函数:main.m; 调用函数:其他m文件;无需运行 运行结果效果图; 2、代码运行版本 Matlab 2019b;若运行有误,根据提示修改;若不会,私信博主; 3、运行操作步骤 步骤一:将所有文件放到Matlab的当前文件夹中; 步骤二:双击打开main.m文件; 步骤三:点击运行,等程序运行完得到结果; 4、仿真咨询 如需其他服务,可私信博主; 4.1 博客或资源的完整代码提供 4.2 期刊或参考文献复现 4.3 Matlab程序定制 4.4 科研合作

    【车间调度】基于matlab多元宇宙算法MVO求解分布式置换流水车间调度DPFSP【含Matlab源码 6138期】.mp4

    海神之光上传的视频是由对应的完整代码运行得来的,完整代码皆可运行,亲测可用,适合小白; 1、从视频里可见完整代码的内容 主函数:main.m; 调用函数:其他m文件;无需运行 运行结果效果图; 2、代码运行版本 Matlab 2019b;若运行有误,根据提示修改;若不会,私信博主; 3、运行操作步骤 步骤一:将所有文件放到Matlab的当前文件夹中; 步骤二:双击打开main.m文件; 步骤三:点击运行,等程序运行完得到结果; 4、仿真咨询 如需其他服务,可私信博主; 4.1 博客或资源的完整代码提供 4.2 期刊或参考文献复现 4.3 Matlab程序定制 4.4 科研合作

    基于MATLAB Simulink R2015b的三电平中性点钳位(NPC)逆变器高级仿真模型,基于MATLAB Simulink R2015b的三电平中性点钳位(NPC)逆变器高级仿真模型,Thre

    基于MATLAB Simulink R2015b的三电平中性点钳位(NPC)逆变器高级仿真模型,基于MATLAB Simulink R2015b的三电平中性点钳位(NPC)逆变器高级仿真模型,Three_Level_NPC_Inverter:基于MATLAB Simulink的三电平中性点钳位(NPC)逆变器仿真模型。 仿真条件:MATLAB Simulink R2015b,拿后前如需转成低版本格式请提前告知,谢谢。 ,核心关键词:Three_Level_NPC_Inverter; MATLAB Simulink; 仿真模型; R2015b版本。,基于MATLAB Simulink的三电平NPC逆变器仿真模型(R2015b版)

    【形状检测】形状特征圆和矩形检测(含尺寸)【含Matlab源码 4625期】.md

    CSDN Matlab武动乾坤上传的资料均是完整代码运行出的仿真结果图,可见完整代码亲测可用,适合小白; 1、完整的代码内容 主函数:main.m; 调用函数:其他m文件;无需运行 运行结果效果图; 2、代码运行版本 Matlab 2019b;若运行有误,根据提示修改;若不会,私信博主; 3、运行操作步骤 步骤一:将所有文件放到Matlab的当前文件夹中; 步骤二:双击打开main.m文件; 步骤三:点击运行,等程序运行完得到结果; 4、仿真咨询 如需其他服务,可私信博主或扫描博客文章底部QQ名片; 4.1 博客或资源的完整代码提供 4.2 期刊或参考文献复现 4.3 Matlab程序定制 4.4 科研合作

    【地震】基于matlab两自由度体系非线性的地震响应【含Matlab源码 11062期】.mp4

    海神之光上传的视频是由对应的完整代码运行得来的,完整代码皆可运行,亲测可用,适合小白; 1、从视频里可见完整代码的内容 主函数:main.m; 调用函数:其他m文件;无需运行 运行结果效果图; 2、代码运行版本 Matlab 2019b;若运行有误,根据提示修改;若不会,私信博主; 3、运行操作步骤 步骤一:将所有文件放到Matlab的当前文件夹中; 步骤二:双击打开main.m文件; 步骤三:点击运行,等程序运行完得到结果; 4、仿真咨询 如需其他服务,可私信博主; 4.1 博客或资源的完整代码提供 4.2 期刊或参考文献复现 4.3 Matlab程序定制 4.4 科研合作

    graph-searcher 机器人路径搜索

    graph_searcher 机器人路径搜索

Global site tag (gtag.js) - Google Analytics