对象池
来源:互联网 发布:js给下拉列表赋值 编辑:程序博客网 时间:2024/06/04 08:16
转自:http://www.cnblogs.com/hsapphire/archive/2010/12/09/1901237.html
在系统设计中,经常会使用“池”的概念。比如数据库连接池,socket连接池,线程池,组件队列。“池”可以节省对象重复创建和初始化所耗费 的时间,可以简化对象获取和使用的过程。对于那些被系统频繁请求和使用的对象,如果使用这种机制,可以使系统性能得到很大提高。特别象数据库连接这种对 象,客户端与数据库服务器端建立连接时,是比较慢的,如果每次进行数据库操作,都要先进行数据库连接,系统效率将非常低下。
“池”的概念就是将被使用的对象事先创建好,保存在列表中,供客户端取用。当客户端取得一个对象时,这个对象就已经是按照特定上下文环境初始化好,马上即 可使用的了。当客户端使用完毕,需要将对象归还给“池”,最后,在系统生命期结束时,由“池”统一释放这些对象。从另一个概念上来说,这也是一种“以空间换时间”的做法,我们在内存中保存一系列整装待命的对象,供人随时差遣。与系统效率相比,这些对象所占用的内存空间太微不足道了。
【池的原理】
“池”的结构是通用的,就是不管他里面保存的是哪一种对象,他的工作方法都基本不变。无非是初始化一系列对象,然后提供一个获取可用对象,一个归还对象的接口。
基于这种考虑,我们可以建立一个通用的对象池,只要某些对象符合“一些基本要求”(这个基本要求,可以使用Interface模式来限定),就可以使用通用对象池来存取和管理。
创建一个接口,用于限定对象池中所保存的对象的基本行为:
public interface IDynamicObject { void Create(Object param); Object GetInnerObject(); bool IsValidate(); void Release(); }
我们在对象池中存放的对象,必须继承上面的接口,并实现接口定义的每一个方法。
Create方法中,用户可以用来创建实际的对象,如建立数据库连接,并打开这个连接;
GetInnerObject方法,使用户可以返回这个实际 的对象,如一个SqlConnection对象;
IsValidate方法是用来判断用户自定义对象的有效性的,是对象池决定是否重新创建对象的标志;
Release方法中,用户可以进行资源释放工作。
有了上面的接口定义,为我们可以在列表中保存用户自定义对象打下了基础。下面就是要实现这个ObjectPool了。
用户自定义对象在我们的ObjectPool中,可以用列表存储,如ArrayList或者Hashtable,为了表示每个用户对象的状态,我们还需要将用户自定义对象包装一下,然后在放到列表中保存。下面定义了一个ObjectPool类的子类,用于包装用户自定义对象:
private class PoolItem { private IDynamicObject _object; private bool _bUsing; private Type _type; private Object _CreateParam; public PoolItem(Type type, Object param) { _type = type; _CreateParam = param; Create(); } private void Create() { _bUsing = false; _object = (IDynamicObject) System.Activator.CreateInstance(_type); _object.Create(_CreateParam); } public void Recreate() { _object.Release(); Create(); } public void Release() { _object.Release(); } public Object InnerObject { get { return _object.GetInnerObject(); } } public int InnerObjectHashcode { get { return InnerObject.GetHashCode(); } } public bool IsValidate { get { return _object.IsValidate(); } } public bool Using { get { return _bUsing; } set { _bUsing = value; } } }
这个类,一个关键的属性是Using,该属性表示对象是否正在被被用户使用。注意,PoolItem创建时,接受一个Object类型的Param参 数,这个参数最后被传递给用户自定义对象的Create方法。用户可以利用这一点,在创建ObjectPool时指定一些参数,供其自定义对象在创建时使 用。比如创建SocketPool时,将服务器IP,端口通过Param传递给自定义对象的Create方法,用户就可以在Create方法中连接指定的 服务器了。
以下是ObjectPool的具体实现代码:
public class ObjectPool { private int _nCapacity; /// <summary> /// 实际的大小 /// </summary> private int _nCurrentSize; private Hashtable _listObjects; private ArrayList _listFreeIndex; private ArrayList _listUsingIndex; private System.Type _typeObject; private Object _objCreateParam; public ObjectPool(System.Type type, Object create_param, int init_size, int capacity) { if (init_size < 0 || capacity < 1 || init_size > capacity) { throw (new System.Exception("Invalid parameter!")); } _nCapacity = capacity; _listObjects = new Hashtable(capacity); _listFreeIndex = new ArrayList(capacity); _listUsingIndex = new ArrayList(capacity); _typeObject = type; _objCreateParam = create_param; for (int i = 0; i < init_size; i++) { PoolItem pitem = new PoolItem(type, create_param); _listObjects.Add(pitem.InnerObjectHashcode, pitem); _listFreeIndex.Add(pitem.InnerObjectHashcode); } _nCurrentSize = _listObjects.Count; } public void Release() { lock (this) { foreach (DictionaryEntry de in _listObjects) { ((PoolItem)de.Value).Release(); } _listObjects.Clear(); _listFreeIndex.Clear(); _listUsingIndex.Clear(); } } public int CurrentSize { get { return _nCurrentSize; } } public int ActiveCount { get { return _listUsingIndex.Count; } } public Object GetOne() { lock (this) { if (_listFreeIndex.Count == 0) { if (_nCurrentSize == _nCapacity) { return null; } PoolItem pnewitem = new PoolItem(_typeObject, _objCreateParam); _listObjects.Add(pnewitem.InnerObjectHashcode, pnewitem); _listFreeIndex.Add(pnewitem.InnerObjectHashcode); _nCurrentSize++; } int nFreeIndex = (int)_listFreeIndex[0]; PoolItem pitem = (PoolItem)_listObjects[nFreeIndex]; _listFreeIndex.RemoveAt(0); _listUsingIndex.Add(nFreeIndex); if (!pitem.IsValidate) { pitem.Recreate(); } pitem.Using = true; return pitem.InnerObject; } } public void FreeObject(Object obj) { lock (this) { int key = obj.GetHashCode(); if (_listObjects.ContainsKey(key)) { PoolItem item = (PoolItem)_listObjects[key]; item.Using = false; _listUsingIndex.Remove(key); _listFreeIndex.Add(key); } } } public int DecreaseSize(int size) { int nDecrease = size; lock (this) { if (nDecrease <= 0) { return 0; } if (nDecrease > _listFreeIndex.Count) { nDecrease = _listFreeIndex.Count; } for (int i = 0; i < nDecrease; i++) { _listObjects.Remove(_listFreeIndex[i]); } _listFreeIndex.Clear(); _listUsingIndex.Clear(); foreach (DictionaryEntry de in _listObjects) { PoolItem pitem = (PoolItem)de.Value; if (pitem.Using) { _listUsingIndex.Add(pitem.InnerObjectHashcode); } else { _listFreeIndex.Add(pitem.InnerObjectHashcode); } } } _nCurrentSize -= nDecrease; return nDecrease; }}
虽然.net对数据库连接已经提供了连接池,但是,经测试,使用上述通用对象池实现的数据库连接池,效率要比直接使用.net管理的连接池高。因为他减少了Open和Close操作,从而节省了时间。
class DBPool { private class SqlConnectionObject : IDynamicObject { private SqlConnection _SqlConn; public SqlConnectionObject() { _SqlConn = null; } #region IDynamicObject Members public void Create(Object param) { String strConn = (String)param; _SqlConn = new SqlConnection(strConn); _SqlConn.Open(); } public Object GetInnerObject() { // TODO: Add SqlConnectionObject.GetInnerObject implementation return _SqlConn; } public bool IsValidate() { return (_SqlConn != null && _SqlConn.GetHashCode() > 0 && _SqlConn.State == ConnectionState.Open); } public void Release() { // TODO: Add SqlConnectionObject.Release implementation _SqlConn.Close(); } #endregion } private ObjectPool _Connections; public DBPool(string connection, int initcount, int capacity) { if (connection == null || connection == "" || initcount < 0 || capacity < 1) { throw (new Exception("Invalid parameter!")); } _Connections = new ObjectPool(typeof(SqlConnectionObject), connection, initcount, capacity); } public SqlConnection GetConnection() { return (SqlConnection)_Connections.GetOne(); } public void FreeConnection(SqlConnection sqlConn) { _Connections.FreeObject(sqlConn); } public void Release() { _Connections.Release(); } public int Count { get { return _Connections.CurrentSize; } } public int UsingCount { get { return _Connections.ActiveCount; } } public int DecreaseSize(int size) { return _Connections.DecreaseSize(size); } }
- 对象池
- 对象池
- 对象池
- 对象池
- 对象池
- 对象池
- 对象池
- 对象池
- 对象池
- 对象池
- 对象池
- 对象池
- 对象池
- 对象池
- 对象池
- 对象池
- 对象池
- 对象池
- 配置Hadoop集群
- python---re模块,正则表达式
- 华硕笔记本(GTX 1060显卡)安装Ubuntu16.04+Nvidia显卡驱动+Cuda8.0+cudnn6.0+ROS+Opencv3.2+Caffe+Tensorflow
- MSRA 电面
- PKI (Public Key Infrastructure 公共密钥基础设施)
- 对象池
- 线程相关的一些问题
- <ICA>Independent Component Analysis与fMRI
- jetty和maven部署项目
- VLC视频播放器原理详细分析含TS流格式分析
- 计算机网络第4章及第5章课后习题答案
- oracle按每天,每周,每月,每季度,每年查询统计数据
- 命令行开发、编译、打包Android应用程序
- JVM基于栈的解释器执行原理