本文介绍本人的一个简单Object Pool实现。什么是Object Pool呢?大家可能都知道什么是数据库连接池,他能极大避免不需要的对象销毁和初始化开销。本文实现的对象池是一个通用的可用于任何有实例化接口的对象的池。默认的对象的实例化接口是new,文中也演示了如果您的对象需要从一个Factory构造,或当你的对象是用Emit生成时,如何简单继承ObjectPool类,实现特殊的对象的池化操作。
主要的类
ObjectPool - 池对象
PoolableAttribute - Poolable属性,可以用于修饰你定义的类,设置池化时的初始参数
SyncGuard - 用于保证线程安全的锁对象,保证ObjectPool可以被多线程安全共享
PoolableAttribute - Poolable属性
我们知道,一个池需要很多基本的参数,包括池的最大最小值等,本类就是用于辅助设置这些信息的。当然,该类和这些属性参数并不是必须的,如果您不给一个类设置该参数,那么,Pool将是用默认的参数值。
该类将允许您设置一下这些参数:
MinPoolSize
MaxPoolSize
PreferedPoolSize //该值表示,当Pool初始化时,希望Pool预先帮您实例化的对象数
CreationTimeout //该值表示,从Pool获取一个对象时的超时时间,一般如果不是内存吃紧,实例化对象本身不太会导致超时,因此,主要的超时原因可能会是因为Pool中的对象数已经达到允许的最大值,此时,从Pool中获取空闲对象的请求会要求等待一个对象空闲出来。因此,这个参数实际上主要用于后面这种超时情形。
using System;
using System.Collections.Generic;
using System.Text;
namespace Ilungasoft.Helper.ObjectPooling
{
[AttributeUsageAttribute(AttributeTargets.Class, AllowMultiple = false)]
public class PoolableAttribute : Attribute
{
Private Members#region Private Members
private int minPoolSize;
private int preferedPoolSize;
private int maxPoolSize;
private long creationTimeout;
/**//// <summary>
/// Checks the state.
/// </summary>
private void CheckState()
{
if (minPoolSize > preferedPoolSize || minPoolSize > maxPoolSize || preferedPoolSize > maxPoolSize)
{
throw new ArgumentException("The condition min <= prefered <= max pool size was not met");
}
if (creationTimeout < -1)
{
creationTimeout = InfiniteCreationTimeout;
}
}
#endregion
Const Members#region Const Members
public const int DefaultMinPoolSize = 1;
public const int DefaultPreferedPoolSize = 16;
public const int DefaultMaxPoolSize = 100000;
public const long DefaultCreationTimeout = 60000;
public const long MaxCreationTimeout = 0x80000000; // ~2 billions
public const long InfiniteCreationTimeout = -1;
#endregion
Public Members#region Public Members
/**//// <summary>
/// Initializes a new instance of the <see cref="T:PoolableAttribute"/> class.
/// </summary>
/// <param name="minPoolSize">Size of the min pool.</param>
/// <param name="preferedPoolSize">Size of the prefered pool.</param>
/// <param name="maxPoolSize">Size of the max pool.</param>
/// <param name="creationTimeout">The creation timeout.</param>
public PoolableAttribute(int minPoolSize, int preferedPoolSize, int maxPoolSize, long creationTimeout)
{
this.minPoolSize = minPoolSize;
this.preferedPoolSize = preferedPoolSize;
this.maxPoolSize = maxPoolSize;
this.creationTimeout = creationTimeout;
CheckState();
}
/**//// <summary>
/// Initializes a new instance of the <see cref="T:PoolableAttribute"/> class.
/// </summary>
/// <param name="minPoolSize">Size of the min pool.</param>
/// <param name="preferedPoolSize">Size of the prefered pool.</param>
/// <param name="maxPoolSize">Size of the max pool.</param>
public PoolableAttribute(int minPoolSize, int preferedPoolSize, int maxPoolSize) : this(minPoolSize, preferedPoolSize, maxPoolSize, DefaultCreationTimeout)
{
}
/**//// <summary>
/// Initializes a new instance of the <see cref="T:PoolableAttribute"/> class.
/// </summary>
public PoolableAttribute()
: this(DefaultMinPoolSize, DefaultPreferedPoolSize, DefaultMaxPoolSize, DefaultCreationTimeout)
{
}
#endregion
Properties#region Properties
/**//// <summary>
/// Gets or sets the size of the min pool.
/// </summary>
/// <value>The size of the min pool.</value>
public int MinPoolSize
{
get
{
return minPoolSize;
}
set
{
minPoolSize = value;
CheckState();
}
}
/**//// <summary>
/// Gets or sets the size of the max pool.
/// </summary>
/// <value>The size of the max pool.</value>
public int MaxPoolSize
{
get
{
return maxPoolSize;
}
set
{
maxPoolSize = value;
CheckState();
}
}
/**//// <summary>
/// Gets or sets the size of the prefered pool.
/// </summary>
/// <value>The size of the prefered pool.</value>
public int PreferedPoolSize
{
get
{
return preferedPoolSize;
}
set
{
preferedPoolSize = value;
CheckState();
}
}
/**//// <summary>
/// Gets or sets the creation timeout.
/// </summary>
/// <value>The creation timeout.</value>
public long CreationTimeout
{
get
{
return creationTimeout;
}
set
{
creationTimeout = value;
CheckState();
}
}
#endregion
}
}
using System.Collections.Generic;
using System.Text;
namespace Ilungasoft.Helper.ObjectPooling
{
[AttributeUsageAttribute(AttributeTargets.Class, AllowMultiple = false)]
public class PoolableAttribute : Attribute
{
Private Members#region Private Members
private int minPoolSize;
private int preferedPoolSize;
private int maxPoolSize;
private long creationTimeout;
/**//// <summary>
/// Checks the state.
/// </summary>
private void CheckState()
{
if (minPoolSize > preferedPoolSize || minPoolSize > maxPoolSize || preferedPoolSize > maxPoolSize)
{
throw new ArgumentException("The condition min <= prefered <= max pool size was not met");
}
if (creationTimeout < -1)
{
creationTimeout = InfiniteCreationTimeout;
}
}
#endregion
Const Members#region Const Members
public const int DefaultMinPoolSize = 1;
public const int DefaultPreferedPoolSize = 16;
public const int DefaultMaxPoolSize = 100000;
public const long DefaultCreationTimeout = 60000;
public const long MaxCreationTimeout = 0x80000000; // ~2 billions
public const long InfiniteCreationTimeout = -1;
#endregion
Public Members#region Public Members
/**//// <summary>
/// Initializes a new instance of the <see cref="T:PoolableAttribute"/> class.
/// </summary>
/// <param name="minPoolSize">Size of the min pool.</param>
/// <param name="preferedPoolSize">Size of the prefered pool.</param>
/// <param name="maxPoolSize">Size of the max pool.</param>
/// <param name="creationTimeout">The creation timeout.</param>
public PoolableAttribute(int minPoolSize, int preferedPoolSize, int maxPoolSize, long creationTimeout)
{
this.minPoolSize = minPoolSize;
this.preferedPoolSize = preferedPoolSize;
this.maxPoolSize = maxPoolSize;
this.creationTimeout = creationTimeout;
CheckState();
}
/**//// <summary>
/// Initializes a new instance of the <see cref="T:PoolableAttribute"/> class.
/// </summary>
/// <param name="minPoolSize">Size of the min pool.</param>
/// <param name="preferedPoolSize">Size of the prefered pool.</param>
/// <param name="maxPoolSize">Size of the max pool.</param>
public PoolableAttribute(int minPoolSize, int preferedPoolSize, int maxPoolSize) : this(minPoolSize, preferedPoolSize, maxPoolSize, DefaultCreationTimeout)
{
}
/**//// <summary>
/// Initializes a new instance of the <see cref="T:PoolableAttribute"/> class.
/// </summary>
public PoolableAttribute()
: this(DefaultMinPoolSize, DefaultPreferedPoolSize, DefaultMaxPoolSize, DefaultCreationTimeout)
{
}
#endregion
Properties#region Properties
/**//// <summary>
/// Gets or sets the size of the min pool.
/// </summary>
/// <value>The size of the min pool.</value>
public int MinPoolSize
{
get
{
return minPoolSize;
}
set
{
minPoolSize = value;
CheckState();
}
}
/**//// <summary>
/// Gets or sets the size of the max pool.
/// </summary>
/// <value>The size of the max pool.</value>
public int MaxPoolSize
{
get
{
return maxPoolSize;
}
set
{
maxPoolSize = value;
CheckState();
}
}
/**//// <summary>
/// Gets or sets the size of the prefered pool.
/// </summary>
/// <value>The size of the prefered pool.</value>
public int PreferedPoolSize
{
get
{
return preferedPoolSize;
}
set
{
preferedPoolSize = value;
CheckState();
}
}
/**//// <summary>
/// Gets or sets the creation timeout.
/// </summary>
/// <value>The creation timeout.</value>
public long CreationTimeout
{
get
{
return creationTimeout;
}
set
{
creationTimeout = value;
CheckState();
}
}
#endregion
}
}
SyncGuard - 用于保证线程安全的锁对象
这个类比较简单,主要就是一个锁,大家看看代码应该就能明白。
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
namespace Ilungasoft.Helper.ObjectPooling
{
internal class SyncGuard
{
Private Members#region Private Members
private object target;
private bool locked;
#endregion
Constructors#region Constructors
/**//// <summary>
/// Initializes a new instance of the <see cref="T:SyncGuard"/> class.
/// </summary>
/// <param name="target">The target.</param>
public SyncGuard(object target)
{
locked = false;
if (target == null)
{
throw new ArgumentNullException("target");
}
this.target = target;
}
/**//// <summary>
using System.Collections.Generic;
using System.Text;
using System.Threading;
namespace Ilungasoft.Helper.ObjectPooling
{
internal class SyncGuard
{
Private Members#region Private Members
private object target;
private bool locked;
#endregion
Constructors#region Constructors
/**//// <summary>
/// Initializes a new instance of the <see cref="T:SyncGuard"/> class.
/// </summary>
/// <param name="target">The target.</param>
public SyncGuard(object target)
{
locked = false;
if (target == null)
{
throw new ArgumentNullException("target");
}
this.target = target;
}
/**//// <summary>