数据库连接池 代码


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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值