首页 > 代码库 > Delphi ThreadPool 线程池(Delphi2009以上版本适用)

Delphi ThreadPool 线程池(Delphi2009以上版本适用)

http://blog.sina.com.cn/s/blog_6250a9df0101kref.html

在网上查找Delphi线程池,结果发现寥寥无几。

看了半天源代码,弄得一头雾水,觉得不容易理解和使用,于是自己想写一个线程池。

什么样的线程池更好呢?

我觉得使用起来要可靠,并且一定要简单,这样才是更好的。

我写的线程池就是这样一个标准,使用非常简单,只传入自己要执行的方法就可以了,

其实大家最后就是关注自己要操作的方法,其余的交给线程池。全部源代码如下:

{  {单元:ThreadPoolUint}  {说明:线程池}  //  {Rev. 开发日期      开发者   EMail}  {Ver.1.0.0   2011/05/05    孙玉良   sunylat@gmail.com}}unit ThreadPoolUint;{ 定义多线程共享读独占写条件编译}{$DEFINE MULTI_THREAD_WRITE_READ}interfaceuses System.Classes, System.SysUtils, System.Math, System.Generics.Collections,  Vcl.Forms;type  { 要执行任务的记录}  TaskRec = record    isSynchronize : Boolean; { 是否需要同步执行}    TaskProc : TThreadProcedure; { 要执行任务的方法}  end;  { 执行具体任务线程}  TExecuteThread = class( TThread )  private    FProc : TThreadProcedure; { 要执行的任务方法}    FIsCanTask : Boolean; { 是否可以执行任务}    FIsSynchronize : Boolean; { 是否用同步执行}    procedure showThreadID; { 显示线程编号(测试使用)}  protected    procedure Execute; override;  public    constructor Create( CreateSuspended : Boolean ); overload;  public    procedure StartTask( task : TaskRec ); { 执行任务}  end;  { 线程池类(单例模式的类,做为全局使用的类)}  ThreadPool = class( TObject )  private{$IFDEF MULTI_THREAD_WRITE_READ}    FMREWSync : TMREWSync; { 共享读独占写变量}{$ENDIF}    FTaskQueue : TQueue< TaskRec >; { 要执行任务队列}    FTaskThreadList : TList< TExecuteThread >; { 执行任务线程List}    FThreadMin : Integer; { 最小线程数量}    FThreadMax : Integer; { 最大线程数量}    { 共享读独占写方法}    procedure BeginWrite; { 独占写开始}    procedure EndWrite; { 独占写结束}    procedure BeginRead; { 共享读开始}    procedure EndRead; { 共享读结束}    procedure StopTaskAndFree; { 停止执行任务并释放相关资源}  protected    constructor CreateInstance( const minCount : Integer = 5;      const maxCount : Integer = 20 );    class function AccessInstance( Request : Integer;      const minCount : Integer = 5; const maxCount : Integer = 20 )      : ThreadPool;  public    constructor Create; { 构造函数}    destructor destroy; override; { 析构函数}    class function Instance( const minCount : Integer = 5;      const maxCount : Integer = 20 ) : ThreadPool; { 实例化函数,客户端调用此函数}    class procedure ReleaseInstance; { 释放资源函数,客户端调用此函数}    procedure AddTask( task : TaskRec ); { 添加要执行的任务}    function IsHaveTask : Boolean; { 是否有要执行的任务}    procedure ExecuteTask; { 执行任务}    function DoNextTask( executeThread : TExecuteThread ) : Boolean; { 执行下一任务}    function IsSuspend( executeThread : TExecuteThread ) : Boolean; { 挂起线程}    function GetPoolState : string; { 得到线程池状态}  end;implementation{$J+}{ MainUnit是为了测试引入的窗体单元,实际使用时候删除此单元和相关代码 }uses MainUnit;{ -----------------------------------------------------------------------------}{ 构造函数}constructor ThreadPool.Create;begin  inherited Create;  raise Exception.CreateFmt( Utils类只能通过Instance方法来创建和访问%s的实例!,    [ ClassName ] );end;{ 创建实例方法}constructor ThreadPool.CreateInstance( const minCount : Integer = 5;  const maxCount : Integer = 20 );var  i : Integer;begin  inherited Create;  { 需要在构造函数中初始化数据全部在此初始化}{$IFDEF MULTI_THREAD_WRITE_READ}  { 创建多线程共享读独占写变量}  Self.FMREWSync := TMREWSync.Create;{$ENDIF}  Self.FTaskQueue := TQueue< TaskRec >.Create; { 实例化要执行的任务队列}  Self.FTaskThreadList := TList< TExecuteThread >.Create; { 实例化执行任务线程List}  Self.FThreadMin := minCount; { 最小线程数量}  Self.FThreadMax := maxCount; { 最大线程数量}  { 创建最小数量的线程}  for i := 0 to minCount - 1 do  begin    { 把线程添加到线程List中}    Self.FTaskThreadList.Add( TExecuteThread.Create( true ) );  end;end;{ 析构函数}destructor ThreadPool.destroy;begin  { 需要析构前完成操作全部在此完成}  Self.StopTaskAndFree; { 释放线程池资源}{$IFDEF MULTI_THREAD_WRITE_READ}  { 释放多线程共享读独占写变量}  Self.FMREWSync.Free;{$ENDIF}  if AccessInstance( 0 ) = Self then  begin    AccessInstance( 2 );  end;  inherited destroy;end;class function ThreadPool.AccessInstance( Request : Integer;  const minCount : Integer = 5; const maxCount : Integer = 20 ) : ThreadPool;const  FInstance : ThreadPool = nil;begin  {    AccessInstance(0):不作任何处理,供释放实例对象时使用。    AccessInstance(1):存在该实例时直接使用,不存在时则创建该实例。    AccessInstance(2):返回一个空指针,用于重新设置实例。  }  case Request of    0 :      ;    1 :      if not Assigned( FInstance ) then      begin        FInstance := CreateInstance( minCount, maxCount );      end;    2 :      FInstance := nil;  else    raise Exception.CreateFmt(  %d 是AccessInstance()中的非法调用参数。, [ Request ] );  end;  Result := FInstance;end;{ 得到类实例}class function ThreadPool.Instance( const minCount : Integer = 5;  const maxCount : Integer = 20 ) : ThreadPool;begin  { 返回实例}  Result := AccessInstance( 1, minCount, maxCount );end;{ 释放资源}class procedure ThreadPool.ReleaseInstance;begin  AccessInstance( 0 ).Free;end;{ ---- 类函数结束 ---- }procedure ThreadPool.StopTaskAndFree;var  whileCount : Integer; { while循环计数变量}  taskThread : TExecuteThread;begin  { 1,释放线程List}  try    Self.BeginWrite;    whileCount := 0; { while循环计数默认值为0}    while whileCount < Self.FTaskThreadList.count do    begin      taskThread := Self.FTaskThreadList.Items[ whileCount ]; { 得到工作线程}      Self.FTaskThreadList.Delete( whileCount ); { 从线程列表中删除线程}      taskThread.Terminate; { 终止线程}      Inc( whileCount ); { while循环计数递增}    end;  finally    Self.EndWrite;    Self.FTaskThreadList.Free; { 释放线程List}  end;  { 2,释放任务队列}  Self.FTaskQueue.Clear;  Self.FTaskQueue.Free;end;{ 独占写开始}procedure ThreadPool.BeginWrite;begin{$IFDEF MULTI_THREAD_WRITE_READ}  Self.FMREWSync.BeginWrite;{$ENDIF}end;{ 独占写结束}procedure ThreadPool.EndWrite;begin{$IFDEF MULTI_THREAD_WRITE_READ}  Self.FMREWSync.EndWrite;{$ENDIF}end;{ 共享读开始}procedure ThreadPool.BeginRead;begin{$IFDEF MULTI_THREAD_WRITE_READ}  Self.FMREWSync.BeginRead;{$ENDIF}end;{ 共享读结束}procedure ThreadPool.EndRead;begin{$IFDEF MULTI_THREAD_WRITE_READ}  Self.FMREWSync.EndRead;{$ENDIF}end;{ 给线程池添加任务}procedure ThreadPool.AddTask( task : TaskRec );begin  { 添加任务到线程池中}  try    Self.BeginWrite;    Self.FTaskQueue.Enqueue( task ); { 把要执行任务加入任务队列}  finally    Self.EndWrite;  end;end;{ 是否有要执行的任务}function ThreadPool.IsHaveTask : Boolean;var  temp : Boolean;begin  temp := false;  try    Self.BeginRead;    { 判断有要执行的任务}    if Self.FTaskQueue.count > 0 then    begin      temp := true;    end;  finally    Self.EndRead;  end;  Result := temp;end;{ 执行任务}procedure ThreadPool.ExecuteTask;var  whileCount : Integer; { while循环计数变量}  isCanCreateThread : Boolean; { 是否可以创建新线程}  curThread : TExecuteThread;begin  { 在主界面memo中显示信息}  Form1.log( 开始执行任务 ); { 测试使用,正式使用删除}  if Self.IsHaveTask then  begin    { 1,判断是否有可以执行任务线程,如果有直接让线程执行}    try      Self.BeginRead;      whileCount := 0; { while循环计数变量默认值为0}      while whileCount < Self.FTaskThreadList.count do      begin        { 判断当前线程为挂起状态}        if Self.FTaskThreadList.Items[ whileCount ].Suspended then        begin          Self.FTaskThreadList.Items[ whileCount ].Resume; { 唤醒挂起线程}        end;        Inc( whileCount ); { while循环计数递增}      end;    finally      Self.EndRead;      { 判断有要执行的任务}      if Self.IsHaveTask then      begin        { 是否可以创建新线程默认值为false}        isCanCreateThread := false;        try          Self.BeginRead;          { 判断当前线程总数小于最大线程数量}          if Self.FTaskThreadList.count < Self.FThreadMax then          begin            isCanCreateThread := true;            {/ /是否可以创建新线程为true}          end;        finally          Self.EndRead;          { 判断可以创建新线程}          if isCanCreateThread then          begin            while Self.FTaskThreadList.count < Self.FThreadMax do            begin              { 创建新线程}              curThread := TExecuteThread.Create( true );              try                Self.BeginWrite;                { 把新线程加入线程List}                Self.FTaskThreadList.Add( curThread );              finally                Self.EndWrite;              end;              curThread.Resume;            end;          end;        end;      end;    end;  end;end;{ 执行下一任务}function ThreadPool.DoNextTask( executeThread : TExecuteThread ) : Boolean;var  isDoNextTask : Boolean; { 是否执行下一任务}  nextTaskRec : TaskRec; { 下一任务结构}  temp : Boolean;begin  temp := false; { 返回布尔值默认值为false}  try    isDoNextTask := false; { 是否执行下一任务默认值为false}    Self.BeginWrite;    { 判断有要执行的任务}    if Self.FTaskQueue.count > 0 then    begin      nextTaskRec := Self.FTaskQueue.Dequeue;      isDoNextTask := true; { 是否执行任务为true}      temp := true; { 返回布尔值为true}    end;  finally    Self.EndWrite;    { 判断执行下一任务}    if isDoNextTask then    begin      executeThread.StartTask( nextTaskRec ); { 执行任务}    end;  end;  Result := temp;end;{ 判断线程是否需要挂起}function ThreadPool.IsSuspend( executeThread : TExecuteThread ) : Boolean;var  temp : Boolean;  isRemove : Boolean;begin  temp := false;  try    Self.BeginRead;    isRemove := false; { 是否从线程List中删除当前线程默认值为false}    { 判断线程数量是否大于最小线程数量}    if Self.FTaskThreadList.count > Self.FThreadMin then    begin      isRemove := true; { 是否从线程List中删除当前线程为true}    end else begin      temp := true; { 是否挂起为true}    end;  finally    Self.EndRead;    { 判断从线程List中删除当前线程}    if isRemove then    begin      try        Self.BeginWrite;        { 从线程List中删除当前线程}        Self.FTaskThreadList.Remove( executeThread );      finally        Self.EndWrite;      end;    end;  end;  Result := temp;end;{ 得到线程池状态}function ThreadPool.GetPoolState : string;var  temp : string; { 返回值变量}  i : Integer; { 循环计数变量}  curThread : TExecuteThread;begin  temp := 线程状态: + #13#10;;  temp := temp + 最小线程数: + inttostr( Self.FThreadMin ) + #13#10;  temp := temp + 最大线程数: + inttostr( Self.FThreadMax ) + #13#10;  try    Self.BeginRead;    temp := temp + 线程总数: + inttostr( Self.FTaskThreadList.count ) + #13#10;    temp := temp + #13#10;    temp := temp + 线程详细信息: + #13#10;    temp := temp + #13#10;    for i := 0 to Self.FTaskThreadList.count - 1 do    begin      curThread := Self.FTaskThreadList.Items[ i ];      temp := temp + 线程- + inttostr( i + 1 ) + #13#10;      temp := temp + 线程编号: + inttostr( curThread.ThreadID ) + #13#10;      { 是否挂起}      if curThread.Suspended then      begin        temp := temp + 是否挂起: True + #13#10;      end else begin        temp := temp + 是否挂起: False + #13#10;      end;      { 是否可以执行任务}      if curThread.FIsCanTask then      begin        temp := temp + 是否可以执行: True + #13#10;      end else begin        temp := temp + 是否可以执行: False + #13#10;      end;      { 是否同步执行任务}      if curThread.FIsSynchronize then      begin        temp := temp + 是否同步执行: True + #13#10;      end else begin        temp := temp + 是否同步执行: False + #13#10;      end;      temp := temp + #13#10;    end;  finally    Self.EndRead;  end;  Result := Trim( temp );end;{ -----------------------------------------------------------------------------}{ 执行任务线程构造函数}constructor TExecuteThread.Create( CreateSuspended : Boolean );begin  inherited Create( CreateSuspended );  FreeOnTerminate := true;  Self.FIsCanTask := false; { 是否可以执行任务默认值为false}  Self.FIsSynchronize := false; { 是否同步执行默认值为false}end;{ 显示线程编号(测试使用)}procedure TExecuteThread.showThreadID;begin  with Form1 do  begin    Memo1.Lines.Add( 停止执行任务线程编号: + inttostr( Self.ThreadID ) )  end;end;{ 执行任务线程的主方法}procedure TExecuteThread.Execute;begin  while not Terminated do  begin    if Terminated then    begin      Break;    end;    { 判断可以执行任务}    if Self.FIsCanTask then    begin      Self.FProc( ); { 执行任务}    end;    { 判断不执行任务}    if ThreadPool.Instance.DoNextTask( Self ) = false then    begin      { 显示执行任务线程编号}      Synchronize( Self.showThreadID ); { 测试使用,正式使用删除}      { 判断挂起当前线程}      if ThreadPool.Instance.IsSuspend( Self ) then      begin        Self.Suspend; { 挂起}      end      else { 不挂起则终止当前线程}      begin        Self.Terminate; { 终止}      end;    end;    { 使界面有反应}    Application.ProcessMessages;  end;end;{ 设置要执行的任务}procedure TExecuteThread.StartTask( task : TaskRec );begin  Self.FProc := task.TaskProc; { 设置要执行的任务}  Self.FIsSynchronize := task.isSynchronize; { 设置是否同步执行}  Self.FIsCanTask := true; { 设置是否可以执行任务为true}end;end.

演示例子代码:

unit MainUnit;interfaceuses  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants,  System.Classes, Vcl.Graphics, System.DateUtils,  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;type  TForm1 = class( TForm )    Button1 : TButton;    Memo1 : TMemo;    Button2 : TButton;    Button3 : TButton;    Button7 : TButton;    teskCountEdt : TEdit;    Button8 : TButton;    useTimeLab : TLabel;    Label1 : TLabel;    procedure Button1Click( Sender : TObject );    procedure Button7Click( Sender : TObject );    procedure Button3Click( Sender : TObject );    procedure FormDestroy( Sender : TObject );    procedure Button2Click( Sender : TObject );    procedure Button8Click( Sender : TObject );  private    { Private declarations }  public    { Public declarations }    procedure log( lgoInfo : string ); {  log方法 }  end;var  Form1 : TForm1;  repeatCount : Integer = 0;  startTime : TDateTime; {  开始时间 }  useTime : Double; {  用时 }implementation{$R *.dfm}uses ThreadPoolUint;procedure TaskFun;var  count : Integer;begin  {  with Form1 do }  {  begin }    {  inc(repeatCount); }    {  Memo1.Lines.Add(FormatDateTime(‘yyyy-mm-dd hh:mm:ss‘, Now) + }  {  ‘ repeat count-‘ + IntToStr(repeatCount)); }    {  count := 50000; }    {  while count > 0 do }  {  begin }  {  Dec(count); }  {  end; }    {  end; }  count := 0;  while count < 100000 do  begin    inc( count );  end;end;procedure TForm1.Button1Click( Sender : TObject );begin  ThreadPool.Instance( 5, 20 );  self.log( 线程池创建了 );end;procedure TForm1.Button2Click( Sender : TObject );var  task : TaskRec;  I : Integer;  timeStr : string;  posInt : Integer;begin  startTime := Now;  useTimeLab.Caption := 0;  {  演示代码开始----------------------- }  {  循环添加要执行的任务 }  {  1,添加要执行任务 }  for I := 0 to StrToInt( teskCountEdt.Text ) - 1 do  begin    {  执行任务记录 }    task.isSynchronize := false;    task.TaskProc := TaskFun;    {  添加要执行的任务 }    ThreadPool.Instance.AddTask( task );  end;  {  2,让线程池执行任务 }  ThreadPool.Instance.ExecuteTask;  {  演示代码结束----------------------- }  useTime := MilliSecondSpan( startTime, Now );  timeStr := FloatToStr( useTime );  posInt := Pos( ., timeStr );  Delete( timeStr, posInt, Length( timeStr ) - ( posInt - 1 ) );  useTimeLab.Caption := 共用时:  + timeStr +  毫秒;end;procedure TForm1.Button3Click( Sender : TObject );begin  self.log( ThreadPool.Instance.GetPoolState ); {  显示线程池状态 }end;procedure TForm1.Button7Click( Sender : TObject );begin  ThreadPool.ReleaseInstance;  self.log( 线程池释放了 );end;procedure TForm1.Button8Click( Sender : TObject );begin  Memo1.Clear;  repeatCount := 0;  useTimeLab.Caption := 0;end;procedure TForm1.FormDestroy( Sender : TObject );begin  ThreadPool.ReleaseInstance;end;procedure TForm1.log( lgoInfo : string );begin  Memo1.Lines.Add( ‘‘ );  Memo1.Lines.Add( FormatDateTime( yyyy-mm-dd hh:mm:ss, Now ) +   +    trim( lgoInfo ) )end;end.

 

调用线程池的代码是:

//1,定义一个要执行任务的结构

task.isSynchronize := false;//是否同步执行

task.TaskProc := TaskFun;//要执行任务方法

 

// 2,向线程池添加要执行的任务

ThreadPool.Instance.AddTask(task);

 

// 3,让线程池执行任务

ThreadPool.Instance.ExecuteTask;

 

如果您有任何建议,请联系:sunylat@gmail.com QQ:14667479

 

Delphi ThreadPool 线程池(Delphi2009以上版本适用)