主要的类
ObjectPool - 池对象
PoolableAttribute - Poolable属性,可以用于修饰你定义的类,设置池化时的初始参数
SyncGuard - 用于保证线程安全的锁对象,保证ObjectPool可以被多线程安全共享
PoolableAttribute - Poolable属性
我们知道,一个池需要很多基本的参数,包括池的最大最小值等,本类就是用于辅助设置这些信息的。当然,该类和这些属性参数并不是必须的,如果您不给一个类设置该参数,那么,Pool将是用默认的参数值。
该类将允许您设置一下这些参数:
MinPoolSize
MaxPoolSize
PreferedPoolSize //该值表示,当Pool初始化时,希望Pool预先帮您实例化的对象数
CreationTimeout //该值表示,从Pool获取一个对象时的超时时间,一般如果不是内存吃紧,实例化对象本身不太会导致超时,因此,主要的超时原因可能会是因为Pool中的对象数已经达到允许的最大值,此时,从Pool中获取空闲对象的请求会要求等待一个对象空闲出来。因此,这个参数实际上主要用于后面这种超时情形。
SyncGuard - 用于保证线程安全的锁对象
这个类比较简单,主要就是一个锁,大家看看代码应该就能明白。
ObjectPool - 池对象
这个类自然是我们的主角了,提供一个对象池需要的接口。这是一个泛型类,有一个类型参数<ObjectType>,这个参数指定需要返回的对象的类型,可以是一个接口。如果您指定的ObjectType可以直接通过new实例化,则可以使用默认构造函数构造Pool; 如果您希望用另一个类(ObjectType的子类或者可实例化的接口实现类),那么,您需要用第二个构造函数来实例化Pool,显式的指定Type。如果,你的类不能通过new直接实例化,或者你希望在实例化后做一些自定义的初始化,那么,后面Teddy也会向您演示怎样继承ObjectPool类获得更大灵活性的自定义。
首先,让我们来看看构造函数,共有两个,上面解释过就不多解释了:
public ObjectPool()
public ObjectPool(Type concreteType)
再来看看主要的Public方法:
public ObjectPool<ObjectType> CreatePool(bool canExhaust) //当实例化一个Pool后,必须显式的调用该函数初始化Pool。
public ObjectPool<ObjectType> CreatePool() //该函数等价于调用上面参数的版本,canExhaust取默认值true
public void DestroyPool() //当您不再需要该Pool时,清空Pool
public ObjectType Draw() //从Pool中获取一个空闲的对象实例
public void Return(ObjectType obj) //当使用完一个对象,必须显式的将对象返回Pool,否则,Pool会认为该对象一直在被使用
下面来说说Protected的Field和方法,Protected的成员用于在继承扩展该类时使得子类可访问:
protected Type type; //实际实例化的对象类型
protected int minSize = PoolableAttribute.DefaultMinPoolSize;
protected int maxSize = PoolableAttribute.DefaultMaxPoolSize;
protected int preferedSize = PoolableAttribute.DefaultPreferedPoolSize;
protected long creationTimeout = PoolableAttribute.DefaultCreationTimeout;
protected static int DefaultGrowSize = 16; //每次对象不够用时,Pool自动新增实例化的对象数
protected virtual void ObtainTypeInformation() //该函数的基类实现,将会读取您指定的对象类型的PoolableAttribute的参数,如果您不希望从PoolableAttribute获取参数而希望从其它地方读取或设定这些参数,可以override该函数
protected virtual ObjectType CreatePoolableObject() //该函数用于创建一个新的对象实例,默认实现当然是简单的new了,如果您希望通过Factory或其它方法来实例化,或者您希望附加一些实例化对象后的初始化工作,可以override该函数
protected virtual bool IsFreeObjectToMuch() //判断Pool中线的对象是否太多了,如果太多了,可能需要销毁一些,节省内存空间,您可以override它以指定自定义的判断逻辑
protected virtual void ShrinkPool() //该函数在基类内,一般会在Draw一个Object之前,先判断IsFreeObjectToMuch(),如果返回true,则调用该函数free一些空闲对象,如果,您希望是用自定义的free逻辑,可以override该函数
好了,类都介绍完了,下面来看看使用示例
1、使用PoolableAttribute修饰一个希望被Pooled的类
2、继承ObjectPool,实现特定的需求。在这个例子中,EntityPool是一个用于PoolEntity的池,我的Entity的实际类型是运行时Emit生成的,因此,只能通过Factory构造,因此,我override了CreatePooledObject方法用Factory方法代替默认实现,并且,我不希望通过PoolableAttribute来设置Pool的参数,所以,我又override了ObtainTypeInformation方法。
3、那么该如何使用Pool?下面演示使用上面这个继承自ObjectPool的EntityPool,如果直接使用ObjectPool完全类似。需要说明一下的是,因为我需要Pool的类型是在运行时由Factory通过Emit生成的,而返回类型About是一个接口,因此,我要在构造EntityPool是指定实际实例化Type。而PooledObjectFactory内使用EntityPool来创建和管理对象。
下面是使用PooledObjectFactory类创建和返回对象实例的示例
About obj1 = PooledEntityFactory<About>.CreateObject();
//...
PooledEntityFactory<About>.ReturnObject(obj1);
//...
PooledEntityFactory<About>.ReturnObject(obj1);
下载ObjectPool源码
Helper.ObjectPooling.zip
//文章结束