1、引入头文件及创建任务队列、锁和条件变量
#include <iostream>
#include <functional>
#include <queue>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <unistd.h>
std::queue<std::function<void()>> taskQueue;
std::mutex mtx;
std::condition_variable cv; // 条件变量,用于线程间的通信
1)其中functional头文件用于表示函数对象的类模板;unistd.h是linux系统定义符号常量的头文件
2)std::function<void()> 这个用来表示一个返回类型为void,无参数的函数
2、创建线程函数及任务函数
void WorkerThread() {
while (true) {
std::function<void()> task;
{
std::unique_lock<std::mutex> lock(mtx);
// 等待任务队列不为空
cv.wait(lock, []{ return !taskQueue.empty(); });
// 从队列中取出任务执行
task = taskQueue.front();
taskQueue.pop();
}
std::thread::id threadID = std::this_thread::get_id();
std::cout << "Inside Thread :: Thread ID : " << threadID << "\n";
task(); // 执行任务
}
}
// 定义一个函数类型,用于包装特定的任务
void MyFun(int i) {
std::cout << "执行内容,任务编号:" << i << std::endl;
sleep(3);
}
1)cv.wait等待两个条件一个是锁一个是队列不为空,当两个条件全部满足时,直接往下执行;当队列为空时,第二个条件不满足,会释放锁,开始阻塞等待。直到其他线程notify_one或notify_all来通知该线程,然后重新判断第二个条件,如果为真,这时开始等待锁,等抢占到锁,开始往下执行。
3、主函数
int main() {
int numTasks = 20;
int numThreads = 5;
std::vector<std::thread> threads;
for (int i = 0; i < numThreads; ++i) {
threads.emplace_back(WorkerThread);
}
for (int i = 0; i < numTasks; ++i) {
// 创建一个Lambda函数,将任务添加到队列中
std::function<void()> task = [i] {
MyFun(i); // 调用封装的函数
};
{
std::unique_lock<std::mutex> lock(mtx);
taskQueue.push(task);
cv.notify_one();
}
}
for (auto& thread : threads) {
thread.join();
}
return 0;
}
1) std::function<void()> task = [i] {
MyFun(i); // 调用封装的函数
}; 这句话是创建一个task对象,这个task是一个lambda对象,捕获 i 变量传入MyFun
2)创建完任务对象,等待任务队列的锁,获得之后push一个task,然后notify某个线程。