前言
在执行并行任务作业的场景时,需要使用到多个线程,如果每次使用到线程时再创建,不用就销毁,这样频繁的创建和销毁线程对于服务器是一个不小的开销。使用线程池就解决了这个问题,在开始一次性创建多个线程,不用的时候进入睡眠,当有任务的时候,就唤醒一个线程执行任务,线程可以不断的重复利用,只需要在开始的一次性的创建,避免的频繁的创建和销毁。
线程池组成
- 工作线程,等待执行分配任务。
- 任务队列,存放待执行的任务。
- 任务接口,用于添加任务
- 管理器,负责线程的创建、启动和停止,任务的调度。
线程池类的定义
class ThreadPool
{
private:
std::vector<std::thread> workers_; //工作线程
std::queue<std::function<void()>> tasks_; //任务队列
std::mutex queue_mutex_; //队列互斥器
std::condition_variable condition_; //条件变量
bool stop_; //是否停止
void Loop(); //线程一直循环等待任务。
public:
ThreadPool(size_t threads=1); //最少一个线程
~ThreadPool();
void Run(const std::function<void()> &func); //启动一个任务
void AddThread(); //增加一个线程
};
线程池类的实现
ThreadPool::ThreadPool(size_t threads) : stop_(false)
{
//获取当前可用硬件实现支持的并发线程数
size_t n = std::thread::hardware_concurrency();
n = std::min(n, threads);
for (size_t i = 0; i < n; i++)
{
workers_.emplace_back([this]{ Loop(); });
}
}
ThreadPool::~ThreadPool()
{
{
std::unique_lock<std::mutex> lock(queue_mutex_);
stop_ = true;
}
//通知所有线程完成任务后退出循环
condition_.notify_all();
for (std::thread &worker : workers_)
{
worker.join();
}
}
void ThreadPool::Loop()
{
while (true)
{
std::function<void()> task;
{
std::unique_lock<std::mutex> lock(queue_mutex_);
//如果stop_不为真,且任务队列还有没执行完的任务,继续执行
condition_.wait(lock, [this] { return this->stop_ || !tasks_.empty(); });
if (stop_ && tasks_.empty()) {
return;
}
task = std::move(tasks_.front());
tasks_.pop();
}
task();
}
}
void ThreadPool::Run(const std::function<void()>& func)
{
//增加一个任务,然后通知一个线程执行
{
std::unique_lock<std::mutex> lock(queue_mutex_);
tasks_.emplace(func);
}
condition_.notify_one();
}
void ThreadPool::AddThread()