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} interface uses 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 = ;
const maxCount : Integer = );
class function AccessInstance( Request : Integer;
const minCount : Integer = ; const maxCount : Integer = )
: ThreadPool;
public
constructor Create; { 构造函数}
destructor destroy; override; { 析构函数}
class function Instance( const minCount : Integer = ;
const maxCount : Integer = ) : 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 = ;
const maxCount : Integer = );
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 := to minCount - 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( ) = Self then
begin
AccessInstance( );
end; inherited destroy;
end; class function ThreadPool.AccessInstance( Request : Integer;
const minCount : Integer = ; const maxCount : Integer = ) : ThreadPool;
const
FInstance : ThreadPool = nil;
begin
{
AccessInstance(0):不作任何处理,供释放实例对象时使用。
AccessInstance(1):存在该实例时直接使用,不存在时则创建该实例。
AccessInstance(2):返回一个空指针,用于重新设置实例。
}
case Request of
:
;
:
if not Assigned( FInstance ) then
begin
FInstance := CreateInstance( minCount, maxCount );
end;
:
FInstance := nil;
else
raise Exception.CreateFmt( ' %d 是AccessInstance()中的非法调用参数。', [ Request ] );
end;
Result := FInstance;
end; { 得到类实例}
class function ThreadPool.Instance( const minCount : Integer = ;
const maxCount : Integer = ) : ThreadPool;
begin
{ 返回实例}
Result := AccessInstance( , minCount, maxCount );
end; { 释放资源}
class procedure ThreadPool.ReleaseInstance;
begin
AccessInstance( ).Free;
end; { ---- 类函数结束 ---- } procedure ThreadPool.StopTaskAndFree;
var
whileCount : Integer; { while循环计数变量}
taskThread : TExecuteThread;
begin
{ 1,释放线程List}
try
Self.BeginWrite; whileCount := ; { 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 > 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 := ; { 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 > 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 := '线程状态:' + ##;; temp := temp + '最小线程数:' + inttostr( Self.FThreadMin ) + ##;
temp := temp + '最大线程数:' + inttostr( Self.FThreadMax ) + ##; try
Self.BeginRead; temp := temp + '线程总数:' + inttostr( Self.FTaskThreadList.count ) + ##;
temp := temp + ##;
temp := temp + '线程详细信息:' + ##;
temp := temp + ##; for i := to Self.FTaskThreadList.count - do
begin
curThread := Self.FTaskThreadList.Items[ i ];
temp := temp + '线程-' + inttostr( i + ) + ##;
temp := temp + '线程编号:' + inttostr( curThread.ThreadID ) + ##; { 是否挂起}
if curThread.Suspended then
begin
temp := temp + '是否挂起: True' + ##;
end else begin
temp := temp + '是否挂起: False' + ##;
end; { 是否可以执行任务}
if curThread.FIsCanTask then
begin
temp := temp + '是否可以执行: True' + ##;
end else begin
temp := temp + '是否可以执行: False' + ##;
end; { 是否同步执行任务}
if curThread.FIsSynchronize then
begin
temp := temp + '是否同步执行: True' + ##;
end else begin
temp := temp + '是否同步执行: False' + ##;
end; temp := temp + ##;
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; interface uses
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 = ; 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 := ;
while count < do
begin
inc( count );
end; end; procedure TForm1.Button1Click( Sender : TObject );
begin
ThreadPool.Instance( , );
self.log( '线程池创建了' );
end; procedure TForm1.Button2Click( Sender : TObject );
var
task : TaskRec;
I : Integer;
timeStr : string;
posInt : Integer;
begin startTime := Now;
useTimeLab.Caption := ''; { 演示代码开始----------------------- } { 循环添加要执行的任务 } { 1,添加要执行任务 }
for I := to StrToInt( teskCountEdt.Text ) - 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 - ) );
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 := ;
useTimeLab.Caption := '';
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以上版本适用)的更多相关文章
- ThreadPool线程池 小结
ThreadPool类提供一个线程池,该线程池可用于发送工作项.处理异步 I/O.代表其他线程等待以及处理计时器 线程池通过为应用程序提供一个由系统管理的辅助线程池使您可以更为有效地使用线程.一个线程 ...
- 转载【浅谈ThreadPool 线程池】
浅谈ThreadPool 线程池 http://www.cnblogs.com/xugang/archive/2010/04/20/1716042.html
- 【多线程】-ThreadPool线程池
ThreadPool介绍: Thread类是一个静态类,所有不存在实例化构造函数操作,直接可以调用其内所存在的方法. 微软官网给出的解释: 提供一个线程池,该线程池可用于执行任务.发送工作项.处理异步 ...
- .net 线程基础 ThreadPool 线程池
1. ThreadPool 线程池异步: //public static bool QueueUserWorkItem(WaitCallback callBack); //public static ...
- 浅谈ThreadPool 线程池(引用)
出自:http://www.cnblogs.com/xugang/archive/2010/04/20/1716042.html 浅谈ThreadPool 线程池 相关概念: 线程池可以看做容纳线程的 ...
- 多线程之旅(ThreadPool 线程池)
一.什么是ThreadPool 线程池(源码) 1.线程池顾名思义,有我们的系统创建一个容器装载着我们的线程,由CLR控制的所有AppDomain共享.线程池可用于执行任务.发送工作项.处理异步 I/ ...
- ThreadPool线程池
1.GetMaxThreads,GetMinThreads class Program { static void Main(string[] args) { int workerThreads; i ...
- ThreadPool(线程池)介绍
>>返回<C# 并发编程> 1. 线程池的由来 1.1. 线程池出现前 1.2. 线程池的诞生 1.3. CLR线程池工作过程 2. 线程池解决的问题 2.1. 异步调用方法 ...
- 多线程 ThreadPool线程池
简单说明一下: 线程池可以看做容纳线程的容器:一个应用程序最多只能有一个线程池:ThreadPool静态类通过QueueUserWorkItem()方法将工作函数排入线程池: 每排入一个工作函数,就相 ...
随机推荐
- windows7操作系统64位安装ArcSDE10.1和Oracle11g
安装环境如下: Oracle11g R2 64位服务端Oracle11g R2 32位客户端(管理员,第二项)ArcSDE10.1 for Oracle11g SDE数据库可由其它机器安装Arcata ...
- 包装类-Character
1,isDigit();是否是数字 char c = '1'; boolean bool = Character.isDigit(c); System.out.println(bool);//true ...
- MySQL · 性能优化· InnoDB buffer pool flush策略漫谈
MySQL · 性能优化· InnoDB buffer pool flush策略漫谈 背景 我们知道InnoDB使用buffer pool来缓存从磁盘读取到内存的数据页.buffer pool通常由数 ...
- iOS 复选框风格转换 Switchery 开关效果
Switchery 是个简单的 JavaScript 组件,只要几个简单的步骤就可以帮助用户把默认的 HTML 复选框转换成漂亮 iOS 7 样式风格.用户可以很方便的自定义这种转换,所以可以很好的配 ...
- Linux基本命令(8)网络操作的命令
网络操作命令 命令 功能 命令 功能 ftp 传送文件 telnet 远端登陆 bye 结束连线并结束程序 rlogin 远端登入 ping 检测主机 netstat 显示网络状态 8.1 ftp命令 ...
- ansible文件模块使用
1. 文件组装模块-assemble assemble主要是将多份配置文件组装为一份配置文件. 参数 必填 默认 选项 说明 Backup 否 No Yes/no 是否创建备份文件,使用时间戳 Del ...
- [Asp.net MVC]Asp.net MVC5系列——Razor语法
Razor视图引擎是Asp.net MVC3中新扩展的内容,并且也是它的默认视图引擎.还有另外一种Web Forms视图引擎.通过前面的文章可知在Asp.net mvc5中创建视图,默认使用的是Raz ...
- Leetcode: Length of Last Word in python
Length of Last Word Total Accepted: 47690 Total Submissions: 168587 Given a string s consists of ...
- 30个有关Python的小技巧
从我开始学习python的时候,我就开始自己总结一个python小技巧的集合.后来当我什么时候在Stack Overflow或者在某个开源软件里看到一段很酷代码的时候,我就很惊讶:原来还能这么做!,当 ...
- httpcomponents 学习1--并发多线程GET
package org.apache.http.examples.client; import org.apache.http.HttpEntity; import org.apache.http.H ...