原理
线程池的工作原理:提前创建一定数量的线程,当有任务需要执行的之后就从线程池中寻找
空闲的现线程来执行任务。
模型
以干饭人为线程,面包为任务,通过一个容器来储存线程,通过一个队列来对任务进行缓冲
代码实现
//线程池
#include<iostream>
#include<queue>
#include<thread>
#include<queue>
#include<vector>
#include<mutex>
#include<condition_variable>
#include<functional>
using namespace std;
//任务函数
void printNumber()
{
static int number = 1;
std::cout << "Number: " << number++ << std::endl;
}
//线程池
class ThreadPool
{
private:
//任务队列
queue<function<void()>>tasks;
//线程容器
vector<thread*>threads;
//互斥锁
std::mutex mtx;
//条件变量
std::condition_variable condition;
//用于结束所有线程
bool stop;
public:
//构造函数
ThreadPool(int threadCnt)
{
stop = false;
//线程执行函数
auto f = [this] {
//函数包装器,用于包装任务函数
function<void()> func ;
while (1)
{
//定义独锁,此线程在争抢任务的时候不让其他线程争夺
std::unique_lock<std::mutex>ulock(mtx);
//争抢任务,只要有任务或者是收到了停止线程的指令stop就不再等待
condition.wait(ulock, [&] {
if (tasks.empty() == false)
{
//获取任务
func =tasks.front();
//任务已被获取,可以将头部任务弹出
tasks.pop();
//执行任务
func();
return true;
}
else if (stop == true)
{
return true;
}
else
{
return false;
}
});
//收到了停止指令还不行,我还要把所有任务都执行完
if (stop == true && tasks.empty() == true)
{
break;
}
}
};
//增加线程
for (int i=0;i<threadCnt;i++)
{
threads.emplace_back(new thread(f));
}
}
//析构函数
~ThreadPool()
{
{
//加锁,在我设置停止命令时,不允许被打断
mtx.lock();
stop = true;
mtx.unlock();
}
//通知所有线程停止指令stop
condition.notify_all();
//依次等待所有线程执行结束
for (int i = 0; i < threads.size(); i++)
{
threads[i]->join();
}
}
//将任务入队
void entasks(std::function<void()>&func)
{
mtx.lock();
tasks.push(func);
mtx.unlock();
}
};
int main(void)
{
//创建线程池
ThreadPool pool(3);
//创建函数包装器
function<void()>func;
//向线程发送任务
for (int i = 0; i < 3; i++)
{
func = printNumber;
pool.entasks(func);
}
return 0;
}