简介
本篇文章主要介绍线程池和定时器的混合使用,实现多线程的时间调度
线程池:一种线程的使用模式,线程过多会带来调度开销,进而影响缓存局部性和整体性能。而线程池维护着多个线程,等待着监督管理者分配可并发执行的任务。这避免了在处理短时间任务时创建与销毁线程的代价。线程池不仅能够保证内核的充分利用,还能防止过分调度。可用线程数量应该取决于可用的并发处理器、处理器内核、内存、网络sockets等的数量。
定时器:本文的定时器是配合线程池一起使用的。
工作方式:1.当新加入一个定时任务,定时器会将任务信息(任务执行时间)加到任务队列中,当任务到期 时投递到线程池中进行处理执行。
2.外部直接投递一个任务到线程池中
系统的组成和工作原理
1.线程池管理
AcsThreadPool类用来管理线程的调度(线程的释放和循环使用)和来自定时器投递的定时任务,AcsThread类会创建一定数量的线程,存到工作线程堆栈_stackThreads中启动线程,根据定时任务状态在空闲的线程中执行。
2.工作线程
线程池中线程,在线程池中等待并执行分配的任务。当定时器投递到期的定时任务时的线程调度方式:
1.如果没有分配线程池就在当前的线程中执行任务;
2.如果分配了线程池,就在线程池中寻找空闲的线程执行任务;
3.如果线程池中没有空闲的线程,且已创建的线程数小于线程池允许的最大线程数,则创建新的新的工作线程执行任务;
4.如果线程池中没有空余的线程,且已创建的线程数大于等于线程池允许的最大线程数,则该次定时 任务就不会被执行了。
另外线程池也可以单独使用(不使用定时器来投递定时任务),外部直接投递任务进线程池,任务在空闲的工作线程中执行,线程调度方式跟定时任务的相同。
3.定时器
在程序中应保持定时器一直在正常工作,每个定时任务都会有个延迟时间,定时任务信息会存储到定时任务的multimap中,这里面是按时间顺序已经排序好的定时任务,当任务到期时就会投递到线程池或当前线程进行处理执行。
主要代码
线程池代码:
AcsThreadPool::AcsThread::AcsThread(AcsThreadPool& pool, int threadID) :
_pool(pool),
_threadID(threadID){
_hevent = event_create(true, false);
_pool._threadCount++;
_pool.add_thread(this);
LOG_INFO("Create thread. number:{}", _pool._threadCount.load());
}
AcsThreadPool::AcsThread::~AcsThread(){
_bStop = true;
if (_hevent) event_set(_hevent);
if (_pthread){
_pthread->join();
delete _pthread;
}
if (_hevent) event_destroy(_hevent);
_pool._threadCount--;
_pool.remove_thread(_threadID);
LOG_INFO("Release thread {}", _pool._threadCount.load());
}
bool AcsThreadPool::AcsThread::thread_st