池通常被实现为在生产者-消费者队列中等待任务项的多个线程。任务是派生自具有“run()”方法的任务类的对象。无论哪个线程获得一个任务,它都会调用 run(),当它返回时,线程循环以从队列中获取另一个任务对象。
这消除了任何线程微管理,并且可以在我尝试过的每种系统/语言上可靠安全地工作。
我所知道的完成通知最灵活的方式是线程在 run() 返回时调用任务的“OnComplete”事件,或者可能是虚拟的“完成”方法,就在循环返回获取下一个任务之前任务,以任务为参数。例如,此方法/事件可以发出一个事件/condvar/sema 信号,任务发起线程正在等待该事件/condvar/sema,可以将已完成的任务排队到发起线程或另一个线程,甚至只是 delete() 任务,(也许它是作业完全在线程池中完成)。
对于错误通知,我会在调用完成方法/事件之前捕获任何由 run() 引发的未捕获异常并将异常存储在 tast 字段中。
除了保护生产者-消费者队列的锁之外,没有其他锁(而且它们只占用足够长的时间来推送/弹出*任务)。
无论您使用哪种设计,请尽量不要:
1) continually create/terminate/destroy threads - avoidable overhead and tricky to manage
2) wait with Join() for any thread to terminate - just don't :)
3) loop around some 'poll thread status' to see if they're finished yet - gets it wrong
4) Move 'working/finished' threads into and out of containers with complicated locks - deadlock-in-the-making
5) use any other sort of micro-management - difficult, messy, error-prone, too many locks, unnecesary, avoidable
理想的线程池是您不知道哪个线程完成工作的地方。事实上,通常甚至不需要保留对线程的任何引用。两行伪线程池:
TblockingQueue *inQueue=new TblockingQueue();
for(int i=0;i<CpoolDepth,i++) new Thread(inQueue);