You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何创建通用C++调度类,实现多类方法的定时线程执行及单实例复用?

方案可行性与实现思路

这个方案完全可行,而且完全可以用单个GenericScheduler实例管理所有三个任务,不需要创建多个实例。下面是具体的实现思路和关键细节:

核心原理:统一不同签名的成员函数

C++的std::function、lambda表达式和std::bind可以轻松将参数不同的run方法包装成调度器能处理的统一签名(比如无参void()函数)。不管Class1::run是带int+string参数,还是Class2::run带double参数,都能被封装成相同类型的可调用对象,供调度器统一管理。

单个GenericScheduler实例的实现方式

让GenericScheduler内部维护一个任务列表,每个任务项包含以下信息:

  • 包装后的目标可调用函数
  • 执行间隔
  • CPU亲和性配置
  • 调度优先级
  • 对应的线程对象

通过模板方法addTask接收任意类的成员函数、参数及调度配置,自动完成函数绑定、线程创建和调度参数设置。

示例代码实现

#include <functional>
#include <thread>
#include <vector>
#include <chrono>
#include <atomic>
#include <pthread.h> // Linux平台,Windows需替换为对应API

class GenericScheduler {
private:
    struct Task {
        std::function<void()> func;
        std::chrono::milliseconds interval;
        cpu_set_t affinity;
        int priority;
        std::thread thread;
        std::atomic<bool> stopFlag{false};
    };
    std::vector<Task> tasks;

    void taskLoop(Task& task) {
        // 设置CPU亲和性(Linux示例)
        pthread_setaffinity_np(task.thread.native_handle(), sizeof(cpu_set_t), &task.affinity);
        // 设置调度优先级(Linux SCHED_FIFO策略)
        struct sched_param param;
        param.sched_priority = task.priority;
        pthread_setschedparam(task.thread.native_handle(), SCHED_FIFO, &param);

        while (!task.stopFlag.load()) {
            try {
                task.func();
            } catch (const std::exception& e) {
                // 处理任务执行异常,避免线程崩溃
                // 比如记录日志:std::cerr << "Task error: " << e.what() << std::endl;
            }
            std::this_thread::sleep_for(task.interval);
        }
    }

public:
    template <typename ClassType, typename... Args>
    void addTask(ClassType* obj, void (ClassType::*runFunc)(Args...), 
                 std::chrono::milliseconds interval, cpu_set_t affinity, int priority, Args... args) {
        // 绑定对象与参数,包装为无参可调用函数
        auto wrappedFunc = [obj, runFunc, args...]() {
            (obj->*runFunc)(args...);
        };

        tasks.emplace_back();
        auto& newTask = tasks.back();
        newTask.func = wrappedFunc;
        newTask.interval = interval;
        newTask.affinity = affinity;
        newTask.priority = priority;
        newTask.thread = std::thread(&GenericScheduler::taskLoop, this, std::ref(newTask));
    }

    // 停止所有任务并等待线程结束
    void stopAll() {
        for (auto& task : tasks) {
            task.stopFlag.store(true);
        }
        waitAll();
    }

    void waitAll() {
        for (auto& task : tasks) {
            if (task.thread.joinable()) {
                task.thread.join();
            }
        }
    }

    ~GenericScheduler() {
        stopAll();
    }
};

// 测试用类
class Class1 {
public:
    void run(int id, const std::string& msg) {
        // 业务逻辑示例
        // std::cout << "Class1 run: id=" << id << ", msg=" << msg << std::endl;
    }
};

class Class2 {
public:
    void run(double value) {
        // 业务逻辑示例
        // std::cout << "Class2 run: value=" << value << std::endl;
    }
};

class Class3 {
public:
    void run() {
        // 业务逻辑示例
        // std::cout << "Class3 run" << std::endl;
    }
};

int main() {
    GenericScheduler scheduler;
    Class1 c1;
    Class2 c2;
    Class3 c3;

    // 配置CPU亲和性(绑定到不同CPU核心)
    cpu_set_t cpuSet1, cpuSet2, cpuSet3;
    CPU_ZERO(&cpuSet1); CPU_SET(0, &cpuSet1);
    CPU_ZERO(&cpuSet2); CPU_SET(1, &cpuSet2);
    CPU_ZERO(&cpuSet3); CPU_SET(2, &cpuSet3);

    // 添加三个不同的任务到同一个调度器实例
    scheduler.addTask(&c1, &Class1::run, std::chrono::milliseconds(1000), cpuSet1, 10, 1001, "hello");
    scheduler.addTask(&c2, &Class2::run, std::chrono::milliseconds(500), cpuSet2, 15, 3.1415);
    scheduler.addTask(&c3, &Class3::run, std::chrono::milliseconds(2000), cpuSet3, 5);

    // 主线程等待(实际项目中可能是其他逻辑)
    std::this_thread::sleep_for(std::chrono::seconds(10));
    scheduler.stopAll();

    return 0;
}

关键注意事项

  • 平台兼容性:示例用了Linux的pthread API处理CPU亲和性和优先级,Windows平台需要替换为SetThreadAffinityMask、SetThreadPriority等API,建议用条件编译处理跨平台逻辑。
  • 异常安全:在任务循环中捕获异常,避免单个任务崩溃导致线程退出。
  • 优雅退出:添加原子停止标志,允许外部触发任务停止,避免强制终止线程。
  • 可扩展性:这个架构很容易扩展,比如添加动态调整任务间隔/优先级、任务启停控制、线程池模式(当任务数量较多时)等功能。

内容的提问来源于stack exchange,提问作者user3746381

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 21:34:53