admin 管理员组

文章数量: 1184232


2024年3月28日发(作者:黑客入门新手教程代码电脑)

维普资讯

第16卷第4期 

2007年12月 

计算机辅助工程 

C0MPUTER AIDED ENGINEERING 

V0I_16 No.4 

Dec.20o7 

文章编号:1006—0871(2007)一04—0068—05 

用设计模式和.Net技术实现对象池设计 

王 翔 

(中国科学院研究生院,北京100049) 

摘要:为有效管理应用程序执行过程中对资源的使用,通过增加对象池,在调用间根据对象状态 

动态共享实例,降低总体资源占用.该对象池原型根据.Net平台配置访问对象和缓冲对象的特点, 

结合状态模式,在抽象可池化对象接口的基础上,实现对池化对象的动态分配与集中管理.单元测 

试表明对象池原型可以根据配置,动态构造、重用、超时回收对象实例.该原型可以为类似模块的 

设计提供参考. 

关键词:.Net;对象池;设计模式 

中图分类号:TP311.132.4 文献标志码:A 

Design on object pool using design pattern and.Net 

WANG Xiang 

(Graduate School,Chinese Academy of Sci.,Beijing 100049,China) 

Abstract:To manage the resources used by application under execution efficiently,an object pool is 

used to reduce the total resource usage by sharing object instance between invokes dynamically according 

to the states of invoked objects.With the.Net configuration and cache types,the prototype implements 

instance dispatch and centralized management by state pattern and design of pooling object interface.The 

unit-tests demonstrate that the prototype can dynamically initialize,reuse and recycle timeout instances 

according to conigfuration.It can provide reference for the design of similar modules. 

Key words:.Net;object pool;design pattern 

O 引 言 

应用运行过程中经常会根据调用要求,生成指 

定类型的对象实例.对于复杂类型的频繁构造会消 

耗较多的系统资源,影响应用运行效率;对于直接与 

用户交互的业务逻辑对象,由于客户端调用的随机 

实例;(2)根据已经池化实例的使用情况,将空闲实 

体直接提供给新的调用,减少重复创建的过程. 

此外,随着.Net和Java等具有自动回收机制¨ 

平台的出现,多数情况下无用实例的回收都由平台 

自动完成,但由于回收机制运行优先级一般都很低, 

在密集业务调用过程中常常会因为无法获得执行机 

性,为每个会话单独保存对象实例会增加应用逻辑 

层系统开销.针对上面两种情况,可以设计1个专门 

管理对象实例的对象池(ObjectPoo1),由它间接控制 

对象实例的构造、激活、失效和释放等过程.对象池 

具有如下运行特性:(1)根据调用动态地生成对象 

收稿日期:2007—05—30修回日期:2007.07.26 

会导致系统资源快速膨胀,因此借助对象池的守卫 

(Guard)控制和实例重用可以比较有效地防止上述 

情况发生.设计模式 描述软件设计过程中某类常 

见问题的一般性解决方法,其中的创建型模式对于 

设计对象池管理和创建类型实例有借鉴作用。采用 

作者简介:王翔(1979一),男,江苏丰县人,高级软件架构师,硕士研究生,研究方向为数据库、信息安全,(E-mail)callwangxiang@gmail.com 

维普资讯

第4期 王翔:用设计模式和.Net技术实现对象池设计 69 

泛型 J一方面是为了提高对象池的执行效率,尤其 

当算法参数类型为值型参数时,可以减少重复装 

箱一拆箱带来的性能损失;另一方面将类型检查提 

前到编译过程. 

1 概要设计 

1.1整体逻辑结构 

根据对象池的运行特征,设计上先划分出如图 

1所示的几个模块. 

图1对象池的总体结构 

通过几个主要模块间的协作,实现运行态的类 

型实例管理,分工如下:(1)Listener模块用于与客 

户程序的交互.一方面将客户程序需要使用的类型 

信息通知Dispatch,另一方面要把加工好的对象实 

例反馈给客户程序,实现对象池对客户程序的透明. 

(2)Dispatch模块的主要工作是调度,根据Listener 

发送的类型要求从ObjectCache中检查是否有已经 

构造完成但没有激活的实例,如果有则直接把实例 

反馈给Listener;否则通知ObjectBuilder创建1个实 

例,在其注册到ObjectCache之后,再反馈给Liste— 

ner.(3)ObjectBuilder模块根据Dispatch输人类型, 

参考其配置参数构造类型实例.(4)Configuration 

Management模块将外部配置信息翻译成配置对象, 

供ObjectBuilder参考.(5)Lease Management模块根 

据池化类型的控制参数,参考ObjectCache中缓冲实 

例的使用情况,回收和清理超期对象.(6)Object— 

Cache模块根据Dispatch调度情况,注册并登记相 

关信息;把ObjectBuilder加工的新实例分类之后,注 

册到缓存. 

1.2池化对象的状态转换 

图2描述对象池管理下对象实体的状态特征. 

Rein'vroke 

图2池化对象的状态转换 

由于池化对象是否可以执行某些功能要依赖于 

自身状态,同时实例自身状态的变化也依赖于池化 

对象的操作,因此产生双向依赖.为了解耦状态类型 

与池化类型间的双向耦合,需要借鉴State模式实现 

池化对象具有自动状态特征的执行方式. 

1.3基本抽象实体类型定义 

基本抽象实体类型静态结构见图3. 

图3基本抽象实体类型静态结构 

IPoolableConfiguration接口定义可池化类型配 

置要求,包括最大池化容量属性(Max)和最长闲置 

时间属性(Timeout)(超时后会被Lease Management 

自动回收). 

IPoolable接口定义可池化类型的基本特征,包 

括GUID编号、类型信息(Type)、创建时间(Create— 

Time)和最近访问时间(AccessedTime).为了执行上 

具有自动状态特征,还有1组与状态管理相关的属 

性和方法. 

IState接口定义状态控制类型的特征,包括是否 

可以执行属性(Executable)和是否没被其他程序占 

用属性(Unoccupied). 

PoolableBase和StateBase分别为实现IPoolable 

接口和IState接口的抽象基类. 

2详细设计 

在进行完整对象池总体静态结构和状态转换设 

计后,下面细化每个模块的设计. 

2.1配置信息管理 

图4为池化对象配置Schema. 

参考.Net Framework对自定义配置节(Configu— 

rationSection)的要求,将对象池配置根节点命名为 

维普资讯

维普资讯

第4期 王翔:用设计模式和.Net技术实现对象池设计 71 

制是对象池的核心组成.此外,业务上经常存在峰值 增加1个静态Available属性,前端Listener可以根 

据Dispatch的可用性决定是否为客户程序提供对象 

池服务(见图10). 

调用,峰值过后如果缓冲的对象过多或过长时间不 

用,也会额外占用很多系统资源,因此需要1个缓冲 

对象的销毁机制(见图9). 

图9 ObjectPool的缓冲和自动销毁机制 

逻辑结构上两部分分别由ObjectCache和Lease 

Management完成,为了实现缓冲的自动管理,设计 

上将两块合并,将Lease Management作为1个独立 

的后台线程池,并以时钟(Timer)方式作为Object— 

Cache的内部成员,按照每个IPoolable类型的 

IPoolableConfiguration信息定时进行回收检查.由 

于.Net的System.Threading.Timer类型作为1个独 

立的线程,通过共享的.Net CLR线程池实现异步自 

动触发调用,因此Lease Management使用该类实现, 

并将Timer和IList<IPoolable>包装为SizeRestifct— 

edIJist<IPoolable>. 

ObjectCache采用享元模式(Fl

盾 

yweight Pattern) 

实现,由于不同池化类型可以配置独立的IPoolable— 

Configuration,因此ObjectCache通过调度一系列池 

化类型列表(SizeRestrictedList<T>)实现集中管理 

所有可池化类型池化后的实例,每个类型列表的信 

息(类型、列表实例)登记在ObjectCache的类型注 

册表(Registry)中. 

2.4 ObjectPooi的调度机制 

为了隔离客户程序对于池化对象实例的创建、 

引用和操作等过程,确保客户程序可以“按需“使用 

具体池化类型实例,在ObjectCache和ObjectBuilder 

上层增加1个Dispatch,工作模式如下:如果Object— 

Cache可以获得1个现成的没有被其他程序占用的 

池化对象实例,直接将其返回;否则根据该种类型的 

池化容量配置,在不超量的情况下,通知Object— 

Builder创建1个新的实例,将其缓冲后再返回;如 

果既无可用缓冲实例也不能继续创建新的实例,则 

返回nul1.考虑到ObjectPool的维护需要,Dispatch 

图10 ObjectPool的调度机制 

2.5 ObjectPooi提供给客户程序的侦听机制 

Listener作为客户程序与ObjectPool交互的代 

理,通过询问Dispatch的Available属性判断是否可 

以对外提供服务(见图1 1).设计上用流型实体类型 

PoolListener<T>(T:IPoolable)完成与不同池化 

类型的交互,其职责T Acquire()方法用于获得特定 

一T 一 

池化类型T的实例(重用1个既有实例或引用1个 

: 

新构造的实例). 

f-……一 

……

匿 

图11 oHectPool服务于客户程序的Listener机制 

3 实验环境准备及实验结果分析 

3.1测试实体类及配置信息 

根据上述设计,完成1个ObjectPool的原型库, 

为验证其有效性,设计如图12所示的两个测试实体 

类用于检查ObjectPool各设计目标是否可以达成. 

测试数据准备见表1. 

图12测试实体类型 

维普资讯

72 

表1测试数据准备 

计算机辅助工程 2007丘 

3.2.3 自动缓冲超时机制测试 

PoolListener<AdvancedCalculator>listener= 

new PoolListener<AdvancedCalculator>(); 

AdvancedCalculator objl=listener.Acquire(); 

obj1.Activate(); 

string guid=obj1.Guid; 

System.Threading.Thread.Sleep(5ooo);//>timeout 

objl=listener.Acquire(); 

3.2测试过程及测试结果分析 

Assert.AreNotEqual<string>(guid,obj1.Guid); 

测试采用.Net测试工程(Test Project),通过断 

结合重用测试的结果,该测试确认对于没有激 

活的objl在超过超时时间等待后,也因之前引用的 

实例被回收,重新访问ObjectPool后获得重新创建 

的实例. 

3.2.4多类型系统管理能力测试 

PoolListener<AdvancedCalculator>11= 

言(Assert)方式对测试程序进行调试,最终可以通 

过的测试用例如下. 

3.2.1缓冲池容量测试 

PoolListener<AdvancedCalculator>listener= 

new PoolListener<AdvancedCalculator>(); 

AdvancedCalculator objl=listener.Acquire(); 

new PoolListener<AdvancedCalculator>(); 

obj1.Activate(); 

Assert.IsNotNull(obj1); 

AdvancedCalculator advanced=11.Acquire(); 

Assert.IsNotNull(advncaed); 

PoolListener<SimpleCalculator>12 = 

AdvancedCalculator ohj2=listener.Acquire(); 

obj2.Activate(); 

Assert.IsNotNull(ohj2); 

AdvancedCalculator ohj3=listener.Acquire(); 

Assert.IsNull(obj3); 

new PoolListener<SimpleCalculator>(); 

SimpleCalculator simple=12.Acquire(); 

simple.Activate(); 

Assert.IsNotNull(simple); 

该测试确认ObjectPool可以根据配置信息控制 

实例数量. 

3.2.2实例重用测试 

PoolListener<AdvancedCalculator>listener= 

该测试确认ObjectPool有可以集中管理多个可 

池化类型能力. 

3.2.5分析 

new PoolListener<AdvancedCalculator>(); 

AdvancedCalculator objl=listener.Acquire(); 

经过上述4个测试。确认ObjectPool原型已具 

有可配置、可重用实例、可自动回收并管理多个池化 

obj1.Activate(); 

AdvancedCalculator obj2=listener.Acuiqre(); 

类型的功能. 

ohj2.Activate(); 

obj1.Deactivate(); 

AdvancedCalculator obj3=listener.Acuiqre(); 

Assert.IsNotNull(ohj3); 

Assetr.AreEqual<string>(obj1.Guid,obj3.Guid); 

Assert.AreEqual<int>(ohj3.Multiple(2,2),2 2); 

4 结束语 

通过在对象池设计中采用合适的设计模式方 

法,确保其可以更加有效地调度池化实例,向客户程 

序透明构造过程,并对实例状态进行管理. 

实际工程中,由于对象池往往需要被多个客户 

该测试确认ObjectPool将objl已经声明暂时不 

程序调用,需要有效的并发机制配合,后续研究中将 

着重对原型的并发能力进行调整. 

用的实例交给ohj3使用. 

参考文献: 

[1]TROELSEN A.Pro c撑2005 and the.Net2.0 platform[M].3版.A Press,2005. 

[2] 伽玛.设计模式——可复用面向对象软件的基础[M].李英军,马晓星,蔡敏,译.北京:机械工业出版社,2005. 

[3] RICHTER J.CLR via c撑[M].2版.周靖,张杰良,译.北京:清华大学出版社,2006. 

(编辑廖粤新) 


本文标签: 对象 实例 类型 池化 设计