前言:公司运转的例子,理解并实现一个简单的线程池
假设你站在上帝视角看一个IT外包公司日常的运转,公司好比是线程池(在代码中体现为main()主函数),
公司每天接商单(Task),接到商单后将加任务队列TaskQueue
公司里的程序猿去完成这些任务Task
每天的上班时间(startWork()),公司每接一个商单就加到任务队列里,到每个员工去领取任务(doTask),如果任务队列中还有任务,谁也不闲着,抢着去做任务(这里模拟体现线程的争夺资源的场景)直到下班时间(getOffWork()).
正常到下班时间员工就下班了(线程退出),但是如果任务队列还没有做完,那就所有员工都加班加点的干,直到干完,或者只有如果某个员工(线程)自己没干完,其他员工可以先下班,没做完的干完后下班.公司一天正常结束(main函数走到return 0).
类图
这里先给出类的个函数的意义,文章最后贴出手搓的所以代码
TaskQueue任务队列
TaskQueue(size_t capa);//构造函数,限定公司每个时刻手上最多能容纳多少个商单
void push(Task* task);//公司将接到的商单放进任务队列
Task* task pop();//员工到时候取出任务
bool empty();//任务队列空
bool full();//任务队列满
private:
size_t m_capacity;
queue<ElemType> m_que;
mutex m_mtx;
condition_variable m_notEmpty;
condition_variable m_notFull;
bool m_flag=false;
ThreadPool公司的内部结构
ThreadPool(size_t threadNum, size_t queSize);//公司今天来了多少个员工
//每个时刻最多拥有多少个商单
void startWork(); //工作时间到
void getOffWork(); //下班时间
void addTask(Task*task); //公司接到的商单添加到任务队列里
Task*task getTask(); //员工获取任务
void doTask(); //员工做任务
private:
size_t m_threadNum;
vector<thread> m_threads;
size_t m_queSize;
TaskQueue m_taskQue;
bool m_isExit;
时序图
公司的一天
int main(){//开始带入公司
ThreadPool t(5,10);//今天公司里来了五个员工
//公司每个时刻最多存在10个商单
//目前还是0个商单
t.startWork(); //上班时间,员工到了,开始抢任务干
int cnt=20; //模拟公司今天一共接了二十个商单
while(cnt--){
t.addTask(new TaskA());//把20个商单A放到任务队列中
}
t.getOffWork();//下班时间,但没做完任务的员工还要继续完成任务才能下班
}