c++中如何实现简单线程池_c++线程池任务调度实现

16次阅读

直接用 std::Thread 不适合高频小任务,因其创建销毁开销大且无法控并发线程池通过复用固定线程、共享阻塞队列和原子停止标志实现高效任务调度。

c++中如何实现简单线程池_c++线程池任务调度实现

为什么直接用 std::thread 不适合高频小任务

频繁创建销毁 std::thread 开销大,线程分配、上下文切换、系统调用都会拖慢性能;任务提交和执行耦合,无法控制并发数,容易压垮系统。线程池本质是复用一组固定线程,把任务排队交给空闲线程处理。

核心组件怎么组织(不依赖第三方库)

一个最小可用线程池需包含:任务队列(std::queue + std::mutex + std::condition_variable)、线程集合(std::vector<:thread>)、停止标志(std::atomic)。所有线程共用一个阻塞队列,通过条件变量等待新任务。

  • 任务类型用 std::function,支持 Lambda、函数指针、绑定对象
  • 入队用 push() 加锁 + 通知,出队用 wait_and_pop() 阻塞等待
  • 线程循环中检查 m_stop.load(),为 true 时主动退出,避免死等
  • 析构时先设 m_stop = true,再 notify_all() 唤醒所有线程,最后 join()

任务调度没那么智能:它只是 FIFO + 竞争获取

标准实现里没有优先级、超时、重试或依赖调度。所谓“调度”就是多个线程同时等待 cv.wait(),谁先被唤醒、谁先抢到互斥锁,谁就取走队首任务——完全由系统调度器决定,不可预测。如果你需要按优先级执行,得换用 std::priority_queue 并加额外同步逻辑;需要延迟执行,就得自己维护定时任务队列,不是线程池本职工作。

一个可运行的极简示例(c++17)

#include  #include  #include  #include  #include  #include  #include   class ThreadPool {     std::vector workers;     std::queue> tasks;     std::mutex queue_mutex;     std::condition_variable cv;     std::atomic m_stop{false};  public:     explicit ThreadPool(size_t threads) {         for (size_t i = 0; i < threads; ++i) {             workers.emplace_back([this] {                 while (true) {                     std::function task;                     {                         std::unique_lock lock(queue_mutex);                         cv.wait(lock, [this] { return m_stop.load() || !tasks.empty(); });                         if (m_stop.load() && tasks.empty()) return;                         task = std::move(tasks.front());                         tasks.pop();                     }                     task();                 }             });         }     }      ~ThreadPool() {         {             std::unique_lock lock(queue_mutex);             m_stop = true;         }         cv.notify_all();         for (auto& t : workers) t.join();     }      template     void enqueue(F&& f, Args&&... args) {         {             std::unique_lock lock(queue_mutex);             tasks.emplace([=] { std::forward(f)(std::forward(args)...); });         }         cv.notify_one();     } };

注意 enqueue 中捕获方式用 [=] 而非 [&],避免引用外部局部变量导致悬垂;notify_one()notify_all() 更轻量,够用;真正上线前还得考虑异常安全——比如 task() 抛异常会终止线程,需要在 worker 循环里加 try/catch

立即学习C++免费学习笔记(深入)”;

text=ZqhQzanResources