惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

C
CERT Recently Published Vulnerability Notes
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
WordPress大学
WordPress大学
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
V
Visual Studio Blog
Stack Overflow Blog
Stack Overflow Blog
aimingoo的专栏
aimingoo的专栏
C
Check Point Blog
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
T
Tor Project blog
P
Proofpoint News Feed
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
Latest news
Latest news
L
LINUX DO - 热门话题
罗磊的独立博客
T
Tenable Blog
The Hacker News
The Hacker News
美团技术团队
N
Netflix TechBlog - Medium
V
Vulnerabilities – Threatpost
阮一峰的网络日志
阮一峰的网络日志
Last Week in AI
Last Week in AI
博客园 - 司徒正美
Jina AI
Jina AI
Cyberwarzone
Cyberwarzone
云风的 BLOG
云风的 BLOG
S
Secure Thoughts
Cloudbric
Cloudbric
S
Security @ Cisco Blogs
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Microsoft Security Blog
Microsoft Security Blog
Spread Privacy
Spread Privacy
U
Unit 42
雷峰网
雷峰网
C
CXSECURITY Database RSS Feed - CXSecurity.com
Webroot Blog
Webroot Blog
爱范儿
爱范儿
博客园 - 【当耐特】
Know Your Adversary
Know Your Adversary
P
Privacy International News Feed
P
Palo Alto Networks Blog
Google Online Security Blog
Google Online Security Blog
The Last Watchdog
The Last Watchdog
博客园 - 聂微东
Help Net Security
Help Net Security
Hacker News: Ask HN
Hacker News: Ask HN
F
Full Disclosure
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
S
Security Affairs
Project Zero
Project Zero

博客园 - 张皓

Stereoscopic Player 1.7.4 (SSP) 加载字幕 layout_weight体验(实现按比例显示) Linux5配置jboss环境 pager-taglib 分页扩展实例 DisplayTag1.2 扩展(自定义分页、排序、导出、页面导航) EJB3在JBoss5内集群探究 maven2 Jetty运行多模块的web application JBoss5开发web service常见问题 jboss启动常见的错误 IDUdpServer研究心得 DLL内线程同步主线程研究(子线程代码放到主线程执行) DBGrid内使用CheckBox功能 子绑定控件获取父绑定项的值 - 张皓 - 博客园 IdTcpServer 用户掉线检测方法 . Net环境下消息队列(MSMQ)对象的应用[转] 消息队列(Message Queue)简介及其使用[转] 分布式事务TransactionScope小结[转] 分布式事务的点滴 调试SQL Server存储过程方法
ADO连接池
张皓 · 2010-09-01 · via 博客园 - 张皓

  Delphi做服务器端如果每次请求都创建一个连接就太耗资源了,而使用一个全局的连接那效率可想而知,这样就体现出了线程池的重要了。参考一些例子做了个ADO的连接池,用到项目中挺不错的,分享下。

{ ******************************************************* }
{ Description : ADO连接池                                 }
{ Create Date : 2010-8-31 23:22:09                        }
{ Modify Remark :2010-9-1 12:00:09                                           }
{ Modify Date :                                           }
{ Version : 1.0                                           }
{ ******************************************************* }

unit ADOConnectionPool;

interface

uses
  Classes, Windows, SyncObjs, SysUtils, ADODB;

type
  TADOConnectionPool = class(TObject)
  private
    FConnectionList:TThreadList;
    //FConnList: TList;
    FTimeout: Integer;
    FMaxCount: Integer;
    FSemaphore: Cardinal;
    //FCriticalSection: TCriticalSection;
    FConnectionString,
    FDataBasePass,
    FDataBaseUser:string;
    function CreateNewInstance(AOwnerList:TList): TADOConnection;
    function GetLock(AOwnerList:TList;Index: Integer): Boolean;
  public
    property ConnectionString:string read FConnectionString write FConnectionString;
    property DataBasePass:string read FDataBasePass write FDataBasePass;
    property DataBaseUser:string read FDataBaseUser write FDataBaseUser;
    property Timeout:Integer read FTimeout write FTimeout;
    property MaxCount:Integer read FMaxCount;

    constructor Create(ACapicity:Integer=15);overload;
    destructor Destroy;override;
    /// <summary>
    /// 申请并一个连接并上锁,使用完必须调用UnlockConnection来释放锁
    /// </summary>
    function LockConnection: TADOConnection;
    /// <summary>
    /// 释放一个连接
    /// </summary>
    procedure UnlockConnection(var Value: TADOConnection);
  end;

type
  PRemoteConnection=^TRemoteConnection;
  TRemoteConnection=record
    Connection : TADOConnection;
    InUse:Boolean;
  end;

var
  ConnectionPool: TADOConnectionPool;

implementation

constructor TADOConnectionPool.Create(ACapicity:Integer=15);
begin
  //FConnList := TList.Create;
  FConnectionList:=TThreadList.Create;
  //FCriticalSection := TCriticalSection.Create;
  FTimeout := 15000;
  FMaxCount := ACapicity;
  FSemaphore := CreateSemaphore(nil, FMaxCount, FMaxCount, nil);
end;

function TADOConnectionPool.CreateNewInstance(AOwnerList:TList): TADOConnection;
var
  p: PRemoteConnection;
begin
  Result := nil;

  New(p);
  p.Connection := TADOConnection.Create(nil);
  p.Connection.ConnectionString := ConnectionString;
  p.Connection.LoginPrompt := False;
  try
    if (DataBaseUser='') and (DataBasePass='') then
      p.Connection.Connected:=True
    else
      p.Connection.Open(DataBaseUser, DataBasePass);
  except
    p.Connection.Free;
    Dispose(p);
    raise;
    Exit;
  end;
  p.InUse := True;
  AOwnerList.Add(p);
  Result := p.Connection;
end;

destructor TADOConnectionPool.Destroy;
var
  i: Integer;
  ConnList:TList;
begin
  //FCriticalSection.Free;
  ConnList:=FConnectionList.LockList;
  try
    for i := ConnList.Count - 1 downto 0 do
    begin
      try
        PRemoteConnection(ConnList[i]).Connection.Free;
        Dispose(ConnList[i]);
      except
        //忽略释放错误
      end;
    end;
  finally
    FConnectionList.UnlockList;
  end;

  FConnectionList.Free;
  CloseHandle(FSemaphore);
  inherited Destroy;
end;

function TADOConnectionPool.GetLock(AOwnerList:TList;Index: Integer): Boolean;
begin
  Result := not PRemoteConnection(AOwnerList[Index]).InUse;
  if Result then
    PRemoteConnection(AOwnerList[Index]).InUse := True;
end;

function TADOConnectionPool.LockConnection: TADOConnection;
var
  i,WaitResult: Integer;
  ConnList:TList;
begin
  Result := nil;
  WaitResult:= WaitForSingleObject(FSemaphore, Timeout);
  if WaitResult = WAIT_FAILED then
    raise Exception.Create('Server busy, please try again');

  ConnList:=FConnectionList.LockList;
  try
    try
      for i := 0 to ConnList.Count - 1 do
      begin
        if GetLock(ConnList,i) then
        begin
          Result := PRemoteConnection(ConnList[i]).Connection;
          Exit;
        end;
      end;
      if ConnList.Count < MaxCount then
        Result := CreateNewInstance(ConnList);
    except
      // 获取信号且失败则释放一个信号量
      if WaitResult=WAIT_OBJECT_0 then
        ReleaseSemaphore(FSemaphore, 1, nil);
      raise;
    end;
  finally
    FConnectionList.UnlockList;
  end;

  if Result = nil then
  begin
    if WaitResult=WAIT_TIMEOUT then
      raise Exception.Create('Timeout expired.Connection pool is full.')
    else
      { This   shouldn 't   happen   because   of   the   sempahore   locks }
      raise Exception.Create('Unable to lock Connection');
  end;
end;

procedure TADOConnectionPool.UnlockConnection(var Value: TADOConnection);
var
  i: Integer;
  ConnList:TList;
begin
  ConnList:=FConnectionList.LockList;
  try
    for i := 0 to ConnList.Count - 1 do
    begin
      if Value = PRemoteConnection(ConnList[i]).Connection then
      begin
        PRemoteConnection(ConnList[I]).InUse := False;
        ReleaseSemaphore(FSemaphore, 1, nil);

        break;
      end;
    end;
  finally
    FConnectionList.UnlockList;
  end;
end;

initialization

ConnectionPool := TADOConnectionPool.Create();

finalization

ConnectionPool.Free;

end.