要在服务端使用对象池的功能,需要在XXX_Impl中uses uROClassFactories单元,并将其initialization小节中代码
TROClassFactory.Create('FirstSampleService', Create_FirstSampleService, TFirstSampleService_Invoker);
替换为
TROPooledClassFactory.Create('FirstSampleService' , //前三个参数不变
Create_FirstSampleService,
TFirstSampleService_Invoker,
10, //池大小
TROPoolBehavior.pbCreateAdditional, 当池内对象已经全部占用该如何做
True); //预先生成池中的对象
跟踪代码看看.原来TROPooledClassFactory继承于TROClassFactory.
constructor TROPooledClassFactory.Create(const anInterfaceName: string;
aCreatorFunc: TRORemotableCreatorFunc; anInvokerClass: TROInvokerClass;
aPoolSize : Integer; aPoolBehavior:TROPoolBehavior=pbCreateAdditional; aPreInitializePool:Boolean=false);
var i : integer;
begin
inherited Create(anInterfaceName, aCreatorFunc, anInvokerClass);
fCriticalSection := TCriticalSection.Create(); //线程同步
SetLength(fInstances, aPoolSize); //设置Array的尺寸为池大小 对象创建出来后保存在这个数组中
fPoolSize := aPoolSize;
fPoolBehavior := aPoolBehavior; //指定如果池中对象都在使用,如何处理新来的请求
if fPoolSize < 1 then RaiseError(err_PoolSizeMustBe1orHigher,[]);
//fLastInc := -1;
if aPreInitializePool then //如果预先生产对象,则调用基类的方法一次创建全部的对象
for i := 0 to (fPoolSize-1) do
inherited CreateInstance(EmptyGUID, fInstances[i].fInterface);
end;
在看看fInstances定义:在类的private中fInstances : array of TROPoolInterfaceEntry;
TROPoolInterfaceEntry = record
fInterface:IInterface;
fInUse:Boolean;
end;
准备就绪了,思路就是提前把一定数量的对象创建出来保存在数组中,如果你来请求的话我就给你返回一个没有使用的对象,并设置fInUse标志位.用完了我在把标志位反置.这样就不用每次都去Create对象了.
由以前的跟踪结果可知,在服务端获取服务对象调用类工厂的CreateInstance方法:aFactory.CreateInstance(aMessage.ClientID, instance);那么这个对象池工厂类就应该要重写CreateInstance方法了.果然其中override了CreateInstance,ReleaseInstance两个方法.
procedure TROPooledClassFactory.CreateInstance(const aClientID : TGUID; out anInstance : IInterface);
var i:Integer;
//, refcnt : integer;
begin
anInstance := nil;
repeat
fCriticalSection.Acquire(); //加锁
try
for I := 0 to fPoolSize-1 do begin //先从数组中查找没有使用的对象
if not fInstances[i].fInUse then begin //如果有没有使用的对象
if not Assigned(fInstances[i].fInterface) then
inherited CreateInstance(EmptyGUID, fInstances[i].fInterface);
anInstance := fInstances[i].fInterface; //返回这个实例
fInstances[i].fInUse := True;
break;
end;
end; { for }
finally
fCriticalSection.Release(); //释放锁
end;
if not Assigned(anInstance) then //如果没有找到空闲的实例
case fPoolBehavior of //根据指定的行为方式
pbFail:raise EROPoolNoFreeObjects.CreateFmt(err_NoFreeObjectsInPool,[GetInterfaceName, fPoolSize]); //抛出异常给客户端
pbWait:Sleep(POOL_SLEEP_MS_WHILE_WAITING); //等待.5秒 继续循环判断 反正这是在单独线程中运行的 不用担心效率问题
pbCreateAdditional:inherited CreateInstance(EmptyGUID, anInstance); //创建新对象
end;
until (fPoolBehavior <> pbWait) or (Assigned(anInstance)); //如果找到或生成了实例 返回
end;
实现真的好简单,系统效率提升设计思路起到决定作用.
procedure TROPooledClassFactory.ReleaseInstance(const aClientID: TGUID; var anInstance: IInterface);
var i:Integer;
begin
fCriticalSection.Acquire(); //加锁
try
//如果对象是从池中获取的,则还回去(设置一下标志位),否则Free掉
for i := 0 to fPoolSize-1 do begin
if fInstances[i].fInterface = anInstance then begin
anInstance := nil;
fInstances[i].fInUse := false;
break;
end;
end;
finally
fCriticalSection.Release();
end;
if Assigned(anInstance) then anInstance := nil;
end;
天色已晚,准备睡觉去了.
联系客服