#include<bits/stdc++.h>
#include<thread>
#include<mutex>
#include<condition_variable>
#include<functional>
//https://www.bilibili.com/video/BV1d841117SH?p=9&vd_source=4943da2c9c0dacb95119f2042d2dfacc
/**
* 线程池:预先开批号线程等待函数调用,因为开辟线程是一个很消耗空间和时间的事情。
*/
class ThreadPool{
public:
ThreadPool(int numThreads): stop(false){
for(int i = 0; i < numThreads; i++){
threads.emplace_back([this]{
while(true){
std::unique_lock<std::mutex> lock(mtx);
condition.wait(lock, [this]{ // 需要阻塞的条件
return !tasks.empty() || stop; // 有任务或者线程终止了,那么就不用等待了。
});
if(stop && tasks.empty()){ // 线程终止,任务队列没有任务,直接终止
return;
}
std::function<void()> task(std::move(tasks.front())); // 从任务队列取任务
tasks.pop();
lock.unlock();
task(); // 在这个线程中执行任务
}
});
}
}
~ThreadPool(){
stop = true;
condition.notify_all(); // 通知线程池中的线程,线程池要终止了
for(auto &t : threads){
t.join();
}
}
template<class T, class... Args> // 函数参数是不确定的,模版和可变参数
void enqueue(T &&f, Args&&... args){
std::function<void()> task =
std::bind(std::forward<T>(f), std::forward<Args>(args)...); // bind函数将函数和参数绑定在一起
{
std::unique_lock<std::mutex> lock(mtx);
tasks.emplace(std::move(task));
}
condition.notify_one(); // 通知一个线程执行任务
}
private:
std::vector<std::thread> threads; //线程队列,有任务就让线程执行。
std::queue<std::function<void()> > tasks; // 任务队列
std::mutex mtx;
std::condition_variable condition; // 生产者消费者模式,需要条件变量通知消费者
std::atomic_bool stop; // 判断线程是否结束 atomic保证操作是原子的
};
int main(){
ThreadPool pool(4);
for(int i = 0; i < 10; i++){
pool.enqueue([i]{
std::cout << " task: " << i << " is running " << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(1));
std::cout << " task: " << i << " is done " << std::endl;
});
}
return 0;
}
C++11 手写线程池
于 2024-03-26 20:02:49 首次发布
本文介绍了一个C++实现的线程池类,使用模板和生产者消费者模式管理任务队列,展示了如何创建线程池并异步执行任务。
摘要由CSDN通过智能技术生成