C++任务调度器:从零构建Task Scheduler

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

C++任务调度器:架构、实现与示例



任务调度器(Task Scheduler)是现代高负载系统、游戏引擎、应用服务器和嵌入式设备的关键组件之一。本文将详细讲解如何利用C++标准库从零创建自己的任务调度器。您将了解任务队列的结构、定时器的工作原理、线程同步方法以及如何避免常见错误。



为什么需要任务调度器?

任务调度器能够:

  • 在后台线程中异步执行代码;
  • 设置延迟执行和周期性触发;
  • 管理执行优先级和执行顺序;
  • 优化CPU资源的使用。

与简单的std::thread不同,调度器提供了灵活的执行控制,并避免为每个任务创建独立线程。



基本架构

任何调度器都由三个主要部分组成:

  • 任务队列——存储任务对象(函数、参数、元数据);
  • 线程池——一个或多个工作线程,从队列中取出任务并执行;
  • 定时器/时间调度器——支持延迟执行或按计划执行任务。


C++任务队列的实现

首先定义任务结构:

struct Task {    std::function<void()> func;    std::chrono::steady_clock::time_point executeAt;    size_t id;};

队列必须是线程安全的。我们使用std::priority_queue(确保执行时间更早的任务优先取出)和std::mutex进行同步:

#include <queue>#include <mutex>#include <condition_variable>#include <functional>#include <chrono>#include <thread>#include <vector>

class TaskScheduler {public: explicit TaskScheduler(size_t threadCount = std::thread::hardware_concurrency()) { for (size_t i = 0; i < threadCount; ++i) { workers.emplace_back([this] { workerLoop(); }); } }

~TaskScheduler() { stop(); }

// 添加带延迟的任务 template<typename F, typename... Args> void schedule(F&& f, Args&&... args, std::chrono::milliseconds delay = std::chrono::milliseconds(0)) { auto task = std::bind(std::forward<F>(f), std::forward<Args>(args)...); Task t{std::move(task), std::chrono::steady_clock::now() + delay, nextId++}; { std::lock_guard<std::mutex> lock(mutex); queue.push(std::move(t)); } cv.notify_one(); }

void stop() { { std::lock_guard<std::mutex> lock(mutex); stopping = true; } cv.notify_all(); for (auto& worker : workers) { if (worker.joinable()) worker.join(); } }

private: struct Task { std::function<void()> func; std::chrono::steady_clock::time_point executeAt; size_t id;

bool operator>(const Task& other) const { return executeAt > other.executeAt; } };

void workerLoop() { while (true) { std::unique_lock<std::mutex> lock(mutex); cv.wait(lock, [this] { return stopping || !queue.empty(); }); if (stopping && queue.empty()) return;

if (!queue.empty()) { auto top = queue.top(); if (std::chrono::steady_clock::now() >= top.executeAt) { queue.pop(); lock.unlock(); top.func

推荐