在系統設計中,經常會使用“池”的概念。比如資料庫連接配接池,socket連接配接池,線程池,元件隊列。“池”可以節省對象重複建立和初始化所耗費 的時間,可以簡化對象擷取和使用的過程。對于那些被系統頻繁請求和使用的對象,如果使用這種機制,可以使系統性能得到很大提高。特别象資料庫連接配接這種對 象,用戶端與資料庫伺服器端建立連接配接時,是比較慢的,如果每次進行資料庫操作,都要先進行資料庫連接配接,系統效率将非常低下。
“池”的概念就是将被使用的對象事先建立好,儲存在清單中,供用戶端取用。當用戶端取得一個對象時,這個對象就已經是按照特定上下文環境初始化好,馬上即 可使用的了。當用戶端使用完畢,需要将對象歸還給“池”,最後,在系統生命期結束時,由“池”統一釋放這些對象。從另一個概念上來說,這也是一種“以空間 換時間”的做法,我們在記憶體中儲存一系列整裝待命的對象,供人随時差遣。與系統效率相比,這些對象所占用的記憶體空間太微不足道了。
“池”的結構是通用的,就是不管他裡面儲存的是哪一種對象,他的工作方法都基本不變。無非是初始化一系列對象,然後提供一個擷取可用對象,一個歸還對象的接口。
基于這種考慮,我們可以建立一個通用的對象池,隻要某些對象符合“一些基本要求”(這個基本要求,可以使用Interface模式來限定),就可以使用通用對象池來存取和管理。
建立一個接口,用于限定對象池中所儲存的對象的基本行為:
複制C#代碼儲存代碼public interface IDynamicObject
{
void Create(Object param);
Object GetInnerObject();
bool IsValidate();
void Release();
}
我們在對象池中存放的對象,必須繼承上面的接口,并實作接口定義的每一個方法。
Create方法中,使用者可以用來建立實際的對象,如建立資料庫連接配接,并打開這個連接配接;GetInnerObject方法,使使用者可以傳回這個實際 的對象,如一個SqlConnection對象;IsValidate方法是用來判斷使用者自定義對象的有效性的,是對象池決定是否重新建立對象的标志; Release方法中,使用者可以進行資源釋放工作。
有了上面的接口定義,為我們可以在清單中儲存使用者自定義對象打下了基礎。下面就是要實作這個ObjectPool了。
使用者自定義對象在我們的ObjectPool中,可以用清單存儲,如ArrayList或者Hashtable,為了表示每個使用者對象的狀态,我們 還需要将使用者自定義對象包裝一下,然後在放到清單中儲存。下面定義了一個ObjectPool類的子類,用于包裝使用者自定義對象:
複制C#代碼儲存代碼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();
public void 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; }
}
}// class PoolItem
這個類,一個關鍵的屬性是Using,該屬性表示對象是否正在被被使用者使用。注意,PoolItem建立時,接受一個Object類型的Param參 數,這個參數最後被傳遞給使用者自定義對象的Create方法。使用者可以利用這一點,在建立ObjectPool時指定一些參數,供其自定義對象在建立時使 用。比如建立SocketPool時,将伺服器IP,端口通過Param傳遞給自定義對象的Create方法,使用者就可以在Create方法中連接配接指定的 伺服器了。powered by 25175.net
以下是ObjectPool的具體實作代碼:
複制C#代碼儲存代碼public sealed class ObjectPool
private Int32 _nCapacity;
private Int32 _nCurrentSize;
private Hashtable _listObjects;
private ArrayList _listFreeIndex;
private ArrayList _listUsingIndex;
private Type _typeObject;
private Object _objCreateParam;
public ObjectPool(Type type, Object create_param, Int32 init_size, Int32 capacity)
if (init_size < 0 || capacity < 1 || init_size > capacity)
{
throw (new 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;
lock (this)
foreach (DictionaryEntry de in _listObjects)
{
((PoolItem) de.Value).Release();
}
_listObjects.Clear();
_listFreeIndex.Clear();
_listUsingIndex.Clear();
}
public Int32 CurrentSize
get { return _nCurrentSize; }
public Int32 ActiveCount
get { return _listUsingIndex.Count; }
public Object GetOne()
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++;
}
Int32 nFreeIndex = (Int32) _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)
int key = obj.GetHashCode();
if (_listObjects.ContainsKey(key))
PoolItem item = (PoolItem) _listObjects[key];
item.Using = false;
_listUsingIndex.Remove(key);
_listFreeIndex.Add(key);
public Int32 DecreaseSize(Int32 size)
Int32 nDecrease = size;
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操作,進而節省了時間。
代碼如下:
複制C#代碼儲存代碼public 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)
_Connections = new ObjectPool(typeof(SqlConnectionObject), connection, initcount, capacity);
public SqlConnection GetConnection()
return (SqlConnection) _Connections.GetOne();
public void FreeConnection(SqlConnection sqlConn)
_Connections.FreeObject(sqlConn);
_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);
} // DBPool
作者:水木