重新实现的db4o连接池

【虎.无名】看了 Roson的db4o连接池实现,似乎存在一些问题:
1,使用sleep或者wait/notify是为了避免循环忙等待,这个非常消耗CPU资源,否则不适合用于生产环境。
2,限制在Jdk1.5以上版本了,并非必要。
3,用户应该可以选择本地模式,还是远程模式;对于后者,需要远程服务器和端口,同时,在代码上,就无需Db4o.openServer了。
于是乎,一时手痒,就重新实现了一个,看看测试效果,虽然达到了互斥,但是db4o内部似乎还存在一些问题。set进去的类,没有成功保存,奇怪中。
/**  
 * Created on 2006-11-24 
 * @author liusheng ([email protected])
 * @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) {
			// 忽略
		}
	}	
}

你可能感兴趣的:(spring,thread,多线程,log4j,OS)