type
TConPool = class
procedure OnMyTimer(Sender: TObject); // 做轮询用
private
FPoolSize: Integer; // 池大小
FMPollingInterval: Integer; // 轮询时间 以 分钟 为单位
FList: TThreadList; // 用来管理连接链表
FTime: TThreadedTimer; // 主要做轮询
FInterval: Integer; // 间隔多少秒 轮询一次 Flist
function GetListCount:Integer; // 返回池中 连接数
procedure SetPoolCount(Value:Integer); // 动态设置池大小
function GetCon(Index: integer): TMyCon; // 返回指定 连接
procedure SetInterval(Value:Integer);
function CreateMyCon(): TMyCon;
public
constructor Create(const MaxNumBer: Integer; FreeMinutes: Integer=5;
TimerTime:Integer = 5000); overload;
destructor Destroy;override;
function GetConFromPool(): TMyCon; // 从池中取出可用的连接
procedure PutConBackPool(pCon: TMyCon); // 释放回归到池中
procedure FreeLongTimeNoUseCon; // 回收池中许久未用的连接
property Count: Integer read GetListCount; //返回已用池大小
property PoolSize: Integer read FPoolSize write SetPoolCount; //池容量属性
property Cons[Index: integer]: TMyCon read GetCon; default;
property Interval: Integer read FInterval write SetInterval;
end;
{ TConPool }
constructor TConPool.Create(const MaxNumBer: Integer;
FreeMinutes: Integer= 5; TimerTime: Integer = 5000);
begin
FPoolSize := MaxNumBer; //设置池大小
FInterval := TimerTime; //设置多少时间 秒 去轮询一次 Flist
FMPollingInterval := FreeMinutes; //连接池中 N 分钟以上没用的自动回收连接池
FList := TThreadList.Create;
FTime := TThreadedTimer.Create(nil);
FTime.Enabled := False;
FTime.Interval := TimerTime; //默认5秒检查一次
FTime.OnTimer := OnMyTimer;
FTime.Enabled := True;
end;
function TConPool.CreateMyCon(): TMyCon;
begin
Result := TMyCon.Create();
if Assigned(Result) then
begin
Result.Working := True;
Result.ActStartTime := Now;
end;
end;
destructor TConPool.Destroy;
var
i: integer;
LockedList: TList;
begin
if Assigned(FTime) then FreeAndNil(FTime);
if Assigned(FList) then
begin
LockedList := FList.LockList;
try
for i := LockedList.Count - 1 downto 0 do
TMyCon(LockedList.Items[i]).Free;
finally
FList.UnlockList;
FreeAndNil(FList);
end;
end;
end;
function TConPool.GetCon(Index: integer): TMyCon;
var
LockedList: TList;
begin
Result := nil;
LockedList := FList.LockList;
try
if (Index < 0) or (Index > LockedList.Count) then Exit;
Result := TMyCon(LockedList.Items[Index]);
finally
FList.UnlockList;
end;
end;
function TConPool.GetListCount: Integer;
var
LockedList: TList;
begin
LockedList := FList.LockList;
try
Result := LockedList.Count;
finally
FList.UnlockList;
end;
end;
function TConPool.GetConFromPool(): TMyCon;
var
i: Integer;
LockedList: TList;
begin
Result := nil;
LockedList := FList.LockList;
try
for i := 0 to LockedList.Count - 1 do
begin
if not TMyCon(LockedList.Items[i]).Working then // 可用(没有在工作)
begin
Result := TMyCon(LockedList.Items[i]);
Result.Working := True; // 标记已经分配用了
Result.ActStartTime := Now; // 记录时间
Break;
end;
end;
//如果池中未找到 则创建
if not Assigned(Result) then
begin
Result := CreateMyCon();
if Assigned(Result) then
begin
//池未满则添加到池中
if LockedList.Count < FPoolSize then
LockedList.Add(Result);
end;
end;
finally
FList.UnlockList;
end;
end;
// 释放一个连接对象 (送回池子里面)
procedure TConPool.PutConBackPool(pCon: TMyCon);
var
I: Integer;
LockedList: TList;
inPool: Boolean;
begin
if not Assigned(pCon) then Exit;
inPool := False;
LockedList := FList.LockList;
try
for i := 0 to LockedList.Count - 1 do
begin
if TMyCon(LockedList.Items[i]) = pCon then
begin
pCon.Working := False;
pCon.ActStartTime := Now;
inPool := True;
Break;
end
end;
if not inPool then
FreeAndNil(pCon);
finally
FList.UnlockList;
end;
end;
procedure TConPool.FreeLongTimeNoUseCon;
var
i: Integer;
LockedList: TList;
function MyMinutesBetween(const ANow, AThen: TDateTime): Integer;
begin
Result := Round(MinuteSpan(ANow, AThen));
end;
begin
LockedList := FList.LockList;
try
for i := LockedList.Count - 1 downto 0 do
begin
if MyMinutesBetween(Now, TMyCon(LockedList.Items[i]).ActStartTime)
>= FMPollingInterval then //释放池子许久不用的 连接
begin
TMyCon(LockedList.Items[i]).Free;
LockedList.Delete(I);
end;
end;
finally
FList.UnlockList;
end;
end;
procedure TConPool.OnMyTimer(Sender: TObject);
begin
FreeLongTimeNoUseCon;
end;
procedure TConPool.SetInterval(Value: Integer);
begin
if FInterval <> Value then FInterval := Value;
end;
procedure TConPool.SetPoolCount(Value: Integer);
begin
//新设置的池大小 不允许 小于 上次设置的大小
if Value = 0 then Exit;
if FPoolSize < Value then FPoolSize := Value;
end;
转载于:https://my.oschina.net/u/582827/blog/1536093