C++实现生产者与消费者模式方式
多线程工作池创建workerCount个工作线程示例中为 3 个每个线程执行相同的workerLoop逻辑。线程通过condition_variable竞争任务队列中的任务确保任务被均匀分发。线程安全保障任务队列的读写仍通过std::mutex保护避免多线程竞争导致的数据错乱。cv.notify_one()每次唤醒一个线程处理任务cv.notify_all()在停止时唤醒所有线程退出。任务分发逻辑生产者主线程提交任务时通过notify_one()唤醒空闲线程避免线程忙等。多个工作线程同时消费任务提升任务处理效率尤其适合 CPU/IO 密集型任务。1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495#include iostream#include mutex#include condition_variable#include queue#include functional#include chrono#include thread#include vector// 任务队列类型usingTask std::functionvoid();intmain() {std::mutex mtx;std::condition_variable cv;std::queueTask taskQueue;boolstop false;// 退出标志constsize_tworkerCount 3;// 工作线程数量std::vectorstd::thread workers;// 工作线程列表// 工作线程循环多线程消费任务 auto workerLoop [](intworkerId) {while(true) {Task task;// 加锁获取任务或检测退出信号{std::unique_lockstd::mutex lock(mtx);// 等待条件有任务 或 需要停止cv.wait(lock, []() {return!taskQueue.empty() || stop;});// 若停止且任务队列为空退出循环if(stop taskQueue.empty()) {std::cout [线程 workerId ] 退出工作循环... std::endl;break;}// 取出队列头部任务多线程竞争确保线程安全task std::move(taskQueue.front());taskQueue.pop();std::cout [线程 workerId ] 取出任务准备执行... std::endl;}// 解锁避免执行任务时持有锁// 执行任务if(task) {task();}}};// 创建多个工作线程 for(inti 0; i workerCount; i) {workers.emplace_back(workerLoop, i);}// 模拟提交任务生产者逻辑 auto submitTask [](Task task) {std::lock_guardstd::mutex lock(mtx);taskQueue.push(std::move(task));std::cout 提交任务当前队列大小 taskQueue.size() std::endl;cv.notify_one();// 唤醒一个等待的工作线程};// 批量提交10个任务for(inti 0; i 10; i) {submitTask([i]() {std::cout 执行任务 i 线程ID std::this_thread::get_id() std::endl;std::this_thread::sleep_for(std::chrono::milliseconds(200));// 模拟任务耗时});}// 等待所有任务执行可选也可通过队列状态判断std::this_thread::sleep_for(std::chrono::seconds(3));// 停止所有工作线程 {std::lock_guardstd::mutex lock(mtx);stop true;cv.notify_all();// 唤醒所有等待的线程确保全部退出std::cout \n通知所有线程停止... std::endl;}// 等待所有工作线程结束for(auto worker : workers) {if(worker.joinable()) {worker.join();}}std::cout 程序结束 std::endl;return0;}总结以上为个人经验希望能给大家一个参考