C++ 任务队列:从理论到实践
任务队列是 C++ 多线程编程中的关键模式之一。它能够高效地在线程之间分配工作,避免数据竞争和资源过度消耗。本文将重点介绍如何在 C++ 中创建和使用任务队列,并强调性能与安全性。
为什么需要任务队列?
在现代应用程序中,经常需要并行执行大量小任务。为每个任务直接创建线程会产生额外开销:创建线程需要时间和内存。任务队列通过线程池解决了这个问题:
- 线程复用 — 线程在完成任务后不会销毁,而是返回池中。
- 负载均衡 — 任务被均匀分配。
- 资源管理 — 限制同时运行的线程数量。
C++ 任务队列的基本实现
我们来看一个简单但线程安全的任务队列,使用 std::queue 和互斥锁。这里使用 C++11 及以上标准库。
#include <queue>#include <mutex>#include <condition_variable>#include <functional>#include <thread>#include <vector>
class TaskQueue {public: using Task = std::function<void()>;
explicit TaskQueue(size_t numThreads) : stop(false) { for (size_t i = 0; i < numThreads; ++i) { workers.emplace_back([this] { workerLoop(); }); } }
~TaskQueue() { { std::unique_lock<std::mutex> lock(mutex); stop = true; } condition.notify_all(); for (auto& worker : workers) { if (worker.joinable()) { worker.join(); } } }
void enqueue(Task task) { { std::unique_lock<std::mutex> lock(mutex); tasks.push(std::move(task)); } condition.notify_one(); }
private: void workerLoop() { while (true) { Task task; { std::unique_lock<std::mutex> lock(mutex); condition.wait(lock, [this] { return stop || !tasks.empty(); }); if (stop && tasks.empty()) { return; } task = std::move(tasks.front()); tasks.pop(); } task(); // 执行任务 } }
std::queue<Task> tasks; std::mutex mutex; std::condition_variable condition; bool stop; std::vector<std::thread> workers;};使用示例
现在演示如何使用我们的 TaskQueue 类来并行执行简单计算:
#include <iostream>
int main() { TaskQueue tq(4); // 4 个线程的线程池
for (int i = 0; i < 10; ++i) { tq.enqueue([i] { std::cout << "任务 " << i << " 由线程 " << std::this_thread::get_id() << " 执行" << std::endl; }); }
// tq 的析构函数会等待所有任务完成 return 0;}高级功能:优先级队列
有时需要按重要性顺序处理任务。为此,可以使用 std::priority_queue 替代普通队列。我们添加优先级支持:
#include <queue>#include <functional>
class PriorityTaskQueue {public: using Task = std::function<void()>;
struct PrioritizedTask { int priority; Task t