首页 > 其他分享 >任务池

任务池

时间:2023-06-18 10:23:16浏览次数:29  
标签:begin task end fThreadNum 任务 TThreadConf procedure

任务池

/// <author>cxg 2020-9-3</author>
/// 线程池处理异步任务队列,每个线程都有自己的任务队列
/// 支持d7以上版本,更低版本没有测试,支持跨OS

unit tasks;

interface

uses
  {$IFDEF mswindows}
  Windows,
  {$ENDIF}
  {$IFDEF posix}
  posix.Unistd, posix.Semaphore,
  {$ENDIF}
  Contnrs, SyncObjs, Classes, SysUtils;

type
  TCallBack = procedure(task: Pointer) of object;

type
  TThreadConf = class
  private
    fCallBack: TCallBack;
    fThreadNum: Cardinal;
    fWorkers: array of TThread;
    fCS: TCriticalSection;
    procedure freeThreads;
    procedure newThreads;
  public
    constructor Create(const threadNum: Cardinal = 0);
    destructor Destroy; override;
  public
    procedure startThreads;
    procedure stopThreads;
    procedure postTask(task: Pointer);
  public
    property onCallback: TCallBack read fCallBack write fCallBack;
    property threadNum: Cardinal read fThreadNum;
  end;

type
  TWorkThread = class(TThread)
  private
    fConf: TThreadConf;
    fQueue: TQueue;
    {$IFDEF mswindows}
    hsem: THandle; // 信号量
    {$ELSE}
    hsem: sem_t;
    {$ENDIF}
  public
    constructor Create(conf: TThreadConf);
    destructor Destroy; override;
  public
    procedure Execute; override;
    procedure push(task: Pointer);
  end;

function cpuNum: Cardinal;

implementation

var
  gIndex: Integer = 0;

function cpuNum: Cardinal;
{$IFDEF MSWINDOWS}
var
  si: SYSTEM_INFO;
{$ENDIF}
begin
  {$IFDEF MSWINDOWS}
  GetSystemInfo(si);
  Result := si.dwNumberOfProcessors;
  {$ELSE}
  Result := sysconf(_SC_NPROCESSORS_ONLN);
  {$ENDIF}
end;

{ TThreadConf }

procedure TThreadConf.postTask(task: Pointer);
var
  i: Integer;
begin
  fCS.Enter;
  try
    i := gIndex mod fThreadNum;
    inc(gIndex);
  finally
    fCS.Leave;
  end;
  TWorkThread(fWorkers[i]).push(task);
end;

constructor TThreadConf.Create(const threadNum: Cardinal = 0);
begin
  fCS := TCriticalSection.Create;
  fThreadNum := threadNum;
  if fThreadNum = 0 then
    fThreadNum := cpuNum;
  SetLength(fWorkers, fThreadNum);
  newThreads;
end;

destructor TThreadConf.Destroy;
begin
  freeThreads;
  FreeAndNil(fCS);
  inherited;
end;

procedure TThreadConf.freeThreads;
var
  i: Integer;
begin
  for i := 0 to fThreadNum - 1 do
  begin
    fWorkers[i].Terminate;
    fWorkers[i].WaitFor;
    FreeAndNil(fWorkers[i]);
  end;
end;

procedure TThreadConf.newThreads;
var
  i: Byte;
begin
  for i := 0 to fThreadNum - 1 do
    fWorkers[i] := TWorkThread.Create(Self);
end;

procedure TThreadConf.startThreads;
var
  i: Byte;
begin
  for i := 0 to fThreadNum - 1 do
    {$IFDEF unicode}
    fWorkers[i].Start;
    {$ELSE}
    fWorkers[i].Resume;
    {$ENDIF}
end;

procedure TThreadConf.stopThreads;
var
  i: Byte;
begin
  for i := 0 to fThreadNum - 1 do
    fWorkers[i].Suspend;
end;

{ TWorkThread }

constructor TWorkThread.Create(conf: TThreadConf);
begin
  inherited Create(True);
  FreeOnTerminate := True;
  fConf := conf;
  fQueue := TQueue.Create;
  {$IFDEF mswindows}
  hsem := CreateSemaphore(nil, 0, 1, nil);
  {$ELSE}
  sem_init(hsem, 0, 0);
  {$ENDIF}
end;

destructor TWorkThread.Destroy;
begin
  FreeAndNil(fQueue);
  {$IFDEF mswindows}
  CloseHandle(hsem);
  {$ELSE}
  sem_destroy(hsem);
  {$ENDIF}
  inherited;
end;

procedure TWorkThread.push(task: Pointer);
begin
  fQueue.Push(task);
  {$IFDEF mswindows}
  ReleaseSemaphore(hsem, 1, nil);
  {$ELSE}
  sem_post(hsem);
  {$ENDIF}
end;

procedure TWorkThread.Execute;
var
  task: Pointer;

  procedure run;
  begin
    task := fQueue.Pop;
    if task <> nil then
      if Assigned(fConf.fCallBack) then
        fConf.fCallBack(task);
  end;

begin
  while not Self.Terminated do
  begin
    {$IFDEF mswindows}
    if WaitForSingleObject(hsem, INFINITE) = WAIT_OBJECT_0 then
      run;
    {$ELSE}
    if sem_wait(hsem) > 0 then
      run;
    {$ENDIF}
  end;
end;

end.

 

标签:begin,task,end,fThreadNum,任务,TThreadConf,procedure
From: https://www.cnblogs.com/hnxxcxg/p/17488774.html

相关文章

  • Centos7 linux定时任务
    1、参考CentOS7定时任务crontab入门Centos利用crontab定时执行任务及配置方法2、crontab-l#查看当前用户定时任务crontab-e#编辑当前用户定时任务#prodbackupdatabase02***cd/data/xxx&&/usr/bin/shxxx_backup.sh#prodautoupdatemanageco......
  • ​任务编排工具在之家业务系统中应用探究
     本文主要介绍在之家广告业务系统中运用任务编排治理工具的场景及其可以解决的问题,讲解任务编排框架的核心要点,以及向大家演示一个任务编排框架的基本结构,让大家对任务编排工具增强业务开发效率,提高研发质量有更深刻的理解。 1.背景我们开始以下面的实际业......
  • 任务调度系统架构设计:基于缓存的改进
    目录1.引言2.技术原理及概念2.2.技术原理介绍3.实现步骤与流程4.示例与应用5.优化与改进随着互联网和信息技术的不断发展,任务调度系统已经成为了企业和个人使用的重要工具。一个高效的任务调度系统可以提高生产效率,降低人工成本,优化工作流程,提高企业竞争力。然而,传统的任务......
  • qt——在主窗口顶层显示一个新窗口,要求新窗口没有边框,不在任务栏显示
     entitulist_ui=newUi::Entitylist;equiplist_ui=newUi::Equiplist;m_entityList=newQWidget(this);m_equipList=newQWidget(this);entitulist_ui->setupUi(m_entityList);equiplist_ui->setupUi(m_equipList);//窗体背景透明m_e......
  • Flink提交任务命令整理
     环境:Flink1.13.6和Flink1.14.4yarn-session模式:--启动yarnseeionbin/yarn-session.sh\-s8\-jm4g\-tm16g\-nmyarn-session-flink\-dyarn-session.sh-jm1g-tm8g-s4-d参数解释:-jm1024表示jobmanager1024M内存-tm1024表示taskmanager......
  • springboot 创建动态定时任务
     首先需要在application中配置注解@EnableScheduling开启定时器初始化定时任务周期就是去数据库查询初始配置的定时任务,如果执行过程中有结果或者没有结果都可以对数据库表进行修改,然后下次再按修改后的时间执行任务 附上数据库表结构packagecom.jiaotongbu.api.common;......
  • springboot-Quartz定时任务并持久化
    新建项目,添加依赖新建一个springboot项目,勾选下springboot,以及quartz依赖 或者我们可以直接在pom.xml文件中直接添加依赖<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-quartz</artifactId>......
  • web worker进程和线程的区别,Chrome 中有哪些常⻅进程,如果我有⼀个耗时很⻓的同步计算
    进程(Process)和线程(Thread)都是操作系统中用于多任务处理的概念。简单地说,一个进程就是一个程序的执行空间,而一个线程则是在执行空间内独立运行的执行路径。区别:进程是系统分配资源的最小单位,线程是操作系统调度的最小单位。各个进程之间是独立的,各个线程之间共享一些资源。创......
  • RPG-任务编辑器
    花了一下午加一上午,中间遇到了一些问题,使用技能:WPF; TextBox 使用Wrapper来完成自动换行,检测回车键,完成换行。使用了System.Web.Extension,来完成json的序列化,也可以用System.Text.Json使用了System.windows.Forms完成文件选择,保存以及文件夹的存放的FileSaveDialog,FolderBro......
  • Spring Boot 实现定时任务动态管理,太爽了!
    一、功能说明SpringBoot的定时任务的加强工具,实现对SpringBoot原生的定时任务进行动态管理,完全兼容原生@Scheduled注解,无需对原本的定时任务进行修改二、快速使用具体的功能已经封装成SpringBoot-starter即插即用:<dependency><groupId>com.github.guoyixing</groupId>......