delphi新语法之泛型实现的对象池模板

摘要:
现在的DELPHI因为支持泛型的语法,所以也能支持模板编程了。
现在的DELPHI因为支持泛型的语法,所以也能支持模板编程了。
// 标准模板
unit UntPools;
interface
uses
Classes, SysUtils, UntThreadTimer;
type
{ 这是一个对像池, 可以池化所有 TObject 对像 }
{ 用法:
在一个全局的地方定义
var
Pooler: TObjectPool;
用到的地方
obj := Pooler.LockObject as Txxx;
try
finally
Pooler.UnlockObject;
end;
初始化
initialization
Pooler := TObjectPool.Create(要收集的类名)
finallization
Pooler.Free;
end;
}
//池中对象 状态
TPoolItem = class
private
FInstance: TObject; //对象
FLocked: Boolean; //是否被使用
FLastTime:TDateTime;//最近活跃时间
public
constructor Create(AInstance: TObject;const IsLocked :Boolean = True);
destructor Destroy; override;
end;
//对象池
TObjectPool = class
private
FCachedList: TThreadList;//对象池 中 对象 列表
FMaxCacheSize,FMinCacheSize: Integer; //对象池最大值,最小值 如不设置系统默认为 20
FCacheHit: Cardinal; //调用对象池 中 对象的 次数
FCreationCount: Cardinal; //创建对象次数
FObjectClass: TClass;
FRequestCount: Cardinal; //调用对象池次数
FAutoReleased: Boolean; //自动释放空闲的对象
FTimer:TThreadedTimer; //多线程计时器
FHourInterval:Integer; //设置间隔时间(小时)
function GetCurObjCount:Integer;
function GetLockObjCount:Integer;
procedure IniMinPools;//初始化最小池对象
procedure SetFHourInterval(iValue:Integer);
protected
function CreateObject: TObject;// 创建对象
procedure OnMyTimer(Sender: TObject);
public
constructor Create(AClass: TClass;MaxPools,MinPools:Integer);
destructor Destroy; override;
function LockObject: TObject;//获取对象
procedure UnlockObject(Instance: TObject); //释放对象
property ObjectClass: TClass read FObjectClass;
property MaxCacheSize: Integer read FMaxCacheSize;//池子大小
property CacheHit: Cardinal read FCacheHit; //调用池子中对象次数
property CreationCount: Cardinal read FCreationCount;//创建对象次数
property RequestCount: Cardinal read FRequestCount;//请求池次数
property RealCount : Integer read GetCurObjCount;//池中对象数量
property LockObjCount: Integer read GetLockObjCount;//池子繁忙的对象数量
property HourInterval: Integer read FHourInterval write SetFHourInterval;
procedure StartAutoFree; //开启自动回收
procedure StopAutoFree; //关闭自动回收
end;
{ TObjectPool<T> }
{ 同样是对像池, 但支持模板 }
{ 用法:
在一个全局的地方定义
var
Pooler: TObjectPool<要收集的类名>;
用到的地方
obj := Pooler.LockObject;
try
finally
Pooler.UnlockObject;
end;
初始化
initialization
Pooler := TObjectPool<要收集的类名>.Create;
finallization
Pooler.Free;
end;
}
TObjectPool<T: class> = class(TObjectPool)
public
constructor Create(const MaxPools:Integer = 0;const MinPools:Integer = 0);
function LockObject: T;
end;
implementation
{TPoolItem }
const
MSecsPerMins = SecsPerMin * MSecsPerSec;
//返回相差的分钟
function MyMinutesBetWeen(const ANow, AThen: TDateTime): Integer;
var
tmpDay:Double;
begin
tmpDay := 0;
if ANow < AThen then
tmpDay := AThen - ANow
else
tmpDay := ANow - AThen;
Result := Round(MinsPerDay * tmpDay);
end;
constructor TPoolItem.Create(AInstance: TObject;const IsLocked :Boolean);
begin
inherited Create;
FInstance := AInstance;
FLocked := IsLocked;
FLastTime := Now;
end;
destructor TPoolItem.Destroy;
begin
if Assigned(FInstance) then FreeAndNil(FInstance);
inherited;
end;
{ TObjectPool }
constructor TObjectPool.Create(AClass: TClass; MaxPools, MinPools: Integer);
begin
inherited Create;
FObjectClass := AClass;
FCachedList := TThreadList.Create;
FMaxCacheSize := MaxPools;
FMinCacheSize := MinPools;
if FMaxCacheSize = 0 then FMaxCacheSize := 20; //系统默认为20个并发
if FMinCacheSize > FMaxCacheSize then FMinCacheSize := FMaxCacheSize;//系统默认最小值为0
FCacheHit := 0;
FCreationCount := 0;
FRequestCount := 0;
IniMinPools; //初始化最小池对象
//计时销毁
FTimer := TThreadedTimer.Create(nil); //计时
FHourInterval := 4; //默认空闲4小时则回收
FTimer.Interval := MSecsPerMins * MinsPerHour * FHourInterval;
FTimer.OnTimer := OnMyTimer;
end;
function TObjectPool.CreateObject: TObject;
begin
Result := FObjectClass.NewInstance;
if Result is TDataModule then
TDataModule(Result).Create(nil)
else if Result is TComponent then
TComponent(Result).Create(nil)
else if Result is TPersistent then
TPersistent(Result).Create
else Result.Create;
end;
destructor TObjectPool.Destroy;
var
I: Integer;
LockedList: TList;
begin
if Assigned(FCachedList) then
begin
LockedList := FCachedList.LockList;
try
for I := 0 to LockedList.Count - 1 do
TPoolItem(LockedList[I]).Free;
finally
FCachedList.UnlockList;
FCachedList.Free;
end;
end;
FTimer.Free;
inherited;
end;
function TObjectPool.GetCurObjCount: Integer;
var
LockedList: TList;
begin
Result := 0;
LockedList := FCachedList.LockList;
try
Result := LockedList.Count;
finally
FCachedList.UnlockList;
end;
end;
function TObjectPool.GetLockObjCount: Integer;
var
LockedList: TList;
i:Integer;
begin
Result := 0;
LockedList := FCachedList.LockList;
try
for I := 0 to LockedList.Count - 1 do
begin
if TPoolItem(LockedList[I]).FLocked then Result := Result + 1;
end;
finally
FCachedList.UnlockList;
end;
end;
procedure TObjectPool.IniMinPools;
var
PoolsObject: TObject;
LockedList: TList;
I: Integer;
begin
LockedList := FCachedList.LockList;
try
for I := 0 to FMinCacheSize - 1 do
begin
PoolsObject := CreateObject;
if Assigned(PoolsObject) then
LockedList.Add(TPoolItem.Create(PoolsObject,False));
end;
finally
FCachedList.UnlockList;
end;
end;
function TObjectPool.LockObject: TObject;
var
LockedList: TList;
I: Integer;
begin
Result := nil;
LockedList := FCachedList.LockList;
try
Inc(FRequestCount);
for i := 0 to LockedList.Count - 1 do
begin
if not TPoolItem(LockedList.Items[i]).FLocked then
begin
Result := TPoolItem(LockedList.Items[i]).FInstance;
TPoolItem(LockedList.Items[i]).FLocked := True;
TPoolItem(LockedList.Items[i]).FLastTime := Now;
Inc(FCacheHit);//从池中取的次数
Break;
end;
end;
//
if not Assigned(Result) then
begin
Result := CreateObject;
//Assert(Assigned(Result));
Inc(FCreationCount);
if LockedList.Count < FMaxCacheSize then //池子容量
LockedList.Add(TPoolItem.Create(Result,True));
end;
finally
FCachedList.UnlockList;
end;
end;
procedure TObjectPool.OnMyTimer(Sender: TObject);
var
i:Integer;
LockedList: TList;
begin
LockedList := FCachedList.LockList;
try
for I := LockedList.Count - 1 downto 0 do
begin
if MyMinutesBetween(Now,TPoolItem(LockedList.Items[i]).FLastTime) >= FHourInterval * MinsPerHour then //释放池子许久不用的ADO
begin
TPoolItem(LockedList.Items[i]).Free;
LockedList.Delete(I);
end;
end;
finally
FCachedList.UnlockList;
end;
end;
procedure TObjectPool.SetFHourInterval(iValue: Integer);
begin
if iValue <= 1 then Exit;
if FHourInterval = iValue then Exit;
FTimer.Enabled := False;
try
FHourInterval := iValue;
FTimer.Interval := MSecsPerMins * MinsPerHour * FHourInterval;
finally
FTimer.Enabled := True;
end;
end;
procedure TObjectPool.StartAutoFree;
begin
if not FTimer.Enabled then FTimer.Enabled := True;
end;
procedure TObjectPool.StopAutoFree;
begin
if FTimer.Enabled then FTimer.Enabled := False;
end;
procedure TObjectPool.UnlockObject(Instance: TObject);
var
LockedList: TList;
I: Integer;
Item: TPoolItem;
begin
LockedList := FCachedList.LockList;
try
Item := nil;
for i := 0 to LockedList.Count - 1 do
begin
Item := TPoolItem(LockedList.Items[i]);
if Item.FInstance = Instance then
begin
Item.FLocked := False;
Item.FLastTime := Now;
Break;
end;
end;
if not Assigned(Item) then Instance.Free;
finally
FCachedList.UnlockList;
end;
end;
// 基于标准模板定义的泛型模板
{ TObjectPool<T> }
constructor TObjectPool<T>.Create(const MaxPools, MinPools: Integer);
begin
inherited Create(T,MaxPools,MinPools);
end;
function TObjectPool<T>.LockObject: T;
begin
Result := T(inherited LockObject);
end;
end.
// 基于泛型模板定义的具体模板
var
FQueryMgr:TObjectPool<TUniQuery>; //Query池子
FDspMgr:TObjectPool<TDataSetProvider>;//DSP池子
FCDSMgr:TObjectPool<TClientDataSet>;//cds池子
FDSMgr :TObjectPool<TDataSource>;//ds池子
FUniSQLMgr:TObjectPool<TUniSQL>;//执行SQL池子
FUniSPMgr :TObjectPool<TUniStoredProc>;//存储过程池子
// 创建具体模板
function QueryMgr:TObjectPool<TUniQuery>;
begin
if not Assigned(FQueryMgr) then
FQueryMgr := TObjectPool<TUniQuery>.Create(1000,20);
Result := FQueryMgr;
end;

免责声明:文章转载自《delphi新语法之泛型实现的对象池模板》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇13 制作模块压缩包、安装模块Delphi中ClientDataSet的用法小结下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

【转载】Perl异常处理方法总结

    程序脚本在运行过程中,总会碰到这样那样的问题,我们会预知一些问题并为其准备好处理代码,而有一些不能预知。好的程序要能尽可能多的处理可能出现的异常问题,本文就总结了一些方法来解决这些异常,当然perl在这个处理了不及其它同类语言,但也不会差到那里。在开始前,我们先盘点一些关于perl的优缺点。0. 历史太悠久了。你可以在1997年的计算机上找到per...

spring事务——try{...}catch{...}中事务不回滚的几种处理方式

当希望在某个方法中添加事务时,我们常常在方法头上添加@Transactional注解 @ResponseBody @RequestMapping(value = "/payment", method = RequestMethod.POST, produces =MediaType.APPLICATION_JSON_VALUE) @Tr...

Delphi 实现窗体自适应调整尺寸以适应不同屏幕分辩率的显示问题

给你一段代码,网上转的:unit uMyClassHelpers;//实现窗体自适应调整尺寸以适应不同屏幕分辩率的显示问题。//        陈小斌,2012年3月5日interfaceUses  SysUtils,Windows,Classes,Graphics, Controls,Forms,Dialogs, Math,typinfo;//  uMy...

MySql数据库连接池专题

转载自:https://www.cnblogs.com/aspirant/p/6747238.html 最近学习mybatis的时候感觉连接池的知识忘记了,所有复习下 一、什么是数据库连接池? 官方:数据库连接池(Connection pooling)是程序启动时建立足够的数据库连接,并将这些连接组成一个连接池,由程序动态地对池中的连接进行申请,使用...

Java 泛型小结

1、什么是泛型?   泛型(Generics )是把类型参数化,运用于类、接口、方法中,可以通过执行泛型类型调用 分配一个类型,将用分配的具体类型替换泛型类型。然后,所分配的类型将用于限制容器内使用的值,这样就无需进行类型转换,还可以在编译时提供更强的类型检查。    2、泛型有什么用?   泛型主要有两个好处:   (1)消除显示的强制类型转换,提高代...

java连接oracle数据库详细代码

详细代码: import java.sql.Connection;import java.sql.DriverManager;import java.sql.PreparedStatement;import java.sql.ResultSet;import java.sql.SQLException; public  class  DBUtil(){ p...