Managing dynamic number of threads

前端 未结 3 475
北恋
北恋 2021-01-05 06:18

First of all, I\'m still familiarizing myself with multi-threading, and don\'t know much terminology. I need to make sure I\'m doing this right, because it\'s a sensitive su

3条回答
  •  一个人的身影
    2021-01-05 06:47

    As explained by @NGLN etc, you need to pool some threads and accept that the easiest way to manage thread numbers is to divorce the actual number of threads from the desired number. Adding threads to the pool is easy - just create some more instances, (passing the producer-consumer task input queue as a parameter so that the thread knows what to wait on). If the desired number of threads is less than that currently existing, you could queue up enough 'poison-pills' to kill off the extra threads.

    Don't keep any list of thread pointers - it's a load of micro-management hassle that's just not necessary, (and will probably go wrong). All you need to keep is a count of the number of desired threads in the pool so you know what action to take when something changes the 'poolDepth' property.

    The event triggers are best loaded into the jobs that are issued to the pool - descend them all from some 'TpooledTask' class that takes an event as a constructor parameter and stores it in some 'FonComplete' TNotifyEvent. The thread that runs the task can call the FonComplete when it's done the job, (with the TpooledTask as the sender parameter) - you don't need to know what thread ran the task.

    Example:

        unit ThreadPool;
    
        interface
    
        uses
          Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
          Dialogs, StdCtrls, contnrs, syncobjs;
    
    
        type
    
        TpooledTask=class(TObject)
        private
          FonComplete:TNotifyEvent;
        protected
          Fparam:TObject;
          procedure execute; virtual; abstract;
        public
          constructor create(onComplete:TNotifyEvent;param:TObject);
        end;
    
        TThreadPool=class(TObjectQueue)
        private
          access:TcriticalSection;
          taskCounter:THandle;
          threadCount:integer;
        public
          constructor create(initThreads:integer);
          procedure addTask(aTask:TpooledTask);
        end;
    
        TpoolThread=class(Tthread)
        private
          FmyPool:TThreadPool;
        protected
          procedure Execute; override;
        public
          constructor create(pool:TThreadPool);
        end;
    
        implementation
    
        { TpooledTask }
    
        constructor TpooledTask.create(onComplete: TNotifyEvent; param: TObject);
        begin
          FonComplete:=onComplete;
          Fparam:=param;
        end;
    
        { TThreadPool }
    
        procedure TThreadPool.addTask(aTask: TpooledTask);
        begin
          access.acquire;
          try
            push(aTask);
          finally
            access.release;
          end;
          releaseSemaphore(taskCounter,1,nil); // release one unit to semaphore
        end;
    
        constructor TThreadPool.create(initThreads: integer);
        begin
          inherited create;
          access:=TcriticalSection.create;
          taskCounter:=createSemaphore(nil,0,maxInt,'');
          while(threadCount

提交回复
热议问题