讲师中心 微信公众号
AI工具推荐 视频效率加速

C++实现带优先级的任务调度器 _ priority_queue用法【实战】

夜枫大大_9497

夜枫大大_9497

发布时间:2026-04-09 21:24:34

|

828人浏览过

|

来源于php中文网

原创

std::priority_queue不能直接当任务调度器,因其仅支持入队、取顶、弹顶,不支持修改优先级、按ID查询或取消任务;需用懒删除、不可变设计或配合std::set等实现动态调度。

c++实现带优先级的任务调度器 _ priority_queue用法【实战】

为什么直接用 std::priority_queue 不能直接当任务调度器?

因为 std::priority_queue 默认只支持「入队 + 取顶 + 弹顶」,不支持修改已有任务的优先级、取消待执行任务、或按 ID 查询任务——而真实调度场景中,你经常要「提前终止高延迟任务」或「动态提升某个任务的紧急度」。

常见错误现象:std::priority_queue 存的是任务副本,改了外部对象的 priority 字段,队列内部完全无感知;调用 pop() 后才发现刚更新过的任务已经“过期”了。

  • 必须把任务设计为不可变(immutable)——构造时定死优先级,后续只允许新增/删除,不许原地修改
  • 若需动态调整,得配合 std::set 或带索引的堆(如 boost::heap::fibonacci_heap),但代价是代码复杂度和内存开销上升
  • std::priority_queue 的比较函数必须是严格弱序;用 >=== 判断会触发未定义行为

如何用 std::priority_queue 实现最小延迟优先的调度器?

典型场景:多个异步 I/O 任务,每个带 deadline 时间戳,越早到期的越先执行。这时优先级不是越大越好,而是越小(时间戳越小)越优先。

关键在自定义比较器:默认 std::priority_queue 是大根堆,要改成小根堆,得传入 std::greater<T> 或自定义 operator< 返回「更高优先级的任务应该排更前」的逻辑。

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

C++
C++

"空空如也"

下载
struct Task {
    int id;
    std::chrono::steady_clock::time_point deadline;
    std::function<void()> action;
    
    // 注意:这里定义的是“谁该先执行”,所以 deadline 更早 → 更小 → 应该返回 true
    bool operator<(const Task& rhs) const {
        return deadline > rhs.deadline; // 注意是 >,不是 <
    }
};

std::priority_queue<Task> queue; // 自动按 deadline 升序排列(最早到期的在 top)
  • 别写成 return deadline < rhs.deadline,否则 top 返回的是最晚到期的任务
  • 如果用 std::chrono::system_clock,注意跨时区或系统时间跳变可能让 deadline 失效;生产环境建议统一用 steady_clock
  • 任务对象含 std::function,需确保捕获的变量生命周期长于调度器;否则 action() 调用时可能访问已析构对象

怎么安全地从队列中移除指定 ID 的任务?

std::priority_queue 没有 erase() 接口,强行遍历并删除会破坏堆结构。正确做法是「懒删除(lazy removal)」:标记任务为已取消,真正 pop 时跳过。

实现要点:

  • Task 加一个 bool cancelled{false} 成员
  • 插入前不检查,插入后可随时设 task.cancelled = true
  • 调度循环中:反复 top() + pop(),直到遇到未取消的任务,再执行
  • 注意:这会导致队列实际大小膨胀,需定期清理(比如每 1000 次调度后重建队列)
while (!queue.empty()) {
    auto task = queue.top();
    queue.pop();
    if (!task.cancelled) {
        task.action();
        break;
    }
}

多线程环境下使用 std::priority_queue 要加几把锁?

一把就够了——所有对队列的读写(pushtoppop)都必须串行。不要试图只锁写、不锁读,因为 top()pop() 组合不是原子的,中间可能被其他线程插入新任务,导致取到过期 top。

常见错误:用 std::shared_mutex 允许多读,结果 top() 返回后、pop() 前,队列被改,pop()std::out_of_range 或行为异常。

  • 推荐用 std::mutexstd::lock_guard,简单可靠
  • 如果调度频率极高(如每微秒一次),锁争用会成瓶颈;此时应考虑无锁队列(如 moodycamel::ConcurrentQueue)+ 外部排序逻辑,而非硬套 priority_queue
  • 避免在持有锁期间执行 task.action();应先 unlock 再调用,防止回调函数里又去抢同一把锁导致死锁

优先级调度真正的难点不在堆操作本身,而在「任务状态一致性」——取消、超时、重试、依赖关系这些语义,没法靠一个容器自动维护。别指望 std::priority_queue 能替你管好生命周期和并发可见性。

热门AI工具

更多
DeepSeek

DeepSeek是一款面向对话、写作、编程和推理场景的AI大模型工具。

WorkBuddy

一款AI办公效率工具,主要用于腾讯云推出的AI原生桌面智能体工作台,适合需要提升相关任务效率的用户。

立刻MV
立刻MV Hot

立刻MV是一款AI文本写作工具,AI 音乐视频(MV)创作工具。

咔片AIPPT

一款在线AI演示文稿制作工具,可根据主题和内容需求辅助生成PPT结构与页面,提高演示材料制作效率。

SkildArt
SkildArt Hot

SkildArt是一款AI文本写作工具,一站式 AI 视觉创作平台。

豆包大模型

豆包大模型是一款由字节跳动推出的企业级大语言模型服务平台。

Laper
Laper Hot

Laper是专为编剧、导演和制片人推出的 AI 原生剧本创作工具。

Loomy
Loomy Hot

一款AI工具,主要用于科大讯飞发布的桌面级 AI 助理,比 OpenClaw 更易用、更安全!,适合需要提升相关任务效率的用户。

火山引擎

火山引擎是一款面向企业的云计算与AI服务平台。

相关专题

更多
硬盘接口类型介绍
硬盘接口类型介绍

硬盘接口类型有IDE、SATA、SCSI、Fibre Channel、USB、eSATA、mSATA、PCIe等等。详细介绍:1、IDE接口是一种并行接口,主要用于连接硬盘和光驱等设备,它主要有两种类型:ATA和ATAPI,IDE接口已经逐渐被SATA接口;2、SATA接口是一种串行接口,相较于IDE接口,它具有更高的传输速度、更低的功耗和更小的体积;3、SCSI接口等等。

3028

2023.10.19

PHP接口编写教程
PHP接口编写教程

本专题整合了PHP接口编写教程,阅读专题下面的文章了解更多详细内容。

4229

2025.10.17

php8.4实现接口限流的教程
php8.4实现接口限流的教程

PHP8.4本身不内置限流功能,需借助Redis(令牌桶)或Swoole(漏桶)实现;文件锁因I/O瓶颈、无跨机共享、秒级精度等缺陷不适用高并发场景。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

3649

2025.12.29

java接口相关教程
java接口相关教程

本专题整合了java接口相关内容,阅读专题下面的文章了解更多详细内容。

366

2026.01.19

堆和栈的区别
堆和栈的区别

堆和栈的区别:1、内存分配方式不同;2、大小不同;3、数据访问方式不同;4、数据的生命周期。本专题为大家提供堆和栈的区别的相关的文章、下载、课程内容,供大家免费下载体验。

4567

2023.07.18

堆和栈区别
堆和栈区别

堆(Heap)和栈(Stack)是计算机中两种常见的内存分配机制。它们在内存管理的方式、分配方式以及使用场景上有很大的区别。本文将详细介绍堆和栈的特点、区别以及各自的使用场景。php中文网给大家带来了相关的教程以及文章欢迎大家前来学习阅读。

2088

2023.08.10

线程和进程的区别
线程和进程的区别

线程和进程的区别:线程是进程的一部分,用于实现并发和并行操作,而线程共享进程的资源,通信更方便快捷,切换开销较小。本专题为大家提供线程和进程区别相关的各种文章、以及下载和课程。

3478

2023.08.10

Python 多线程与异步编程实战
Python 多线程与异步编程实战

本专题系统讲解 Python 多线程与异步编程的核心概念与实战技巧,包括 threading 模块基础、线程同步机制、GIL 原理、asyncio 异步任务管理、协程与事件循环、任务调度与异常处理。通过实战示例,帮助学习者掌握 如何构建高性能、多任务并发的 Python 应用。

1009

2025.12.24

Buffalo框架数据库开发全教程
Buffalo框架数据库开发全教程

本专题围绕Buffalo框架数据库开发,讲解database.yml多环境配置、soda与fizz迁移生成回滚、模型结构体标签、增删改查与条件查询、一对多与多对多关联、数据校验、回调钩子、事务处理及原生SQL执行能力。

0

2026.09.23

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Conan 2 Essentials 免费课程
Conan 2 Essentials 免费课程

共0课时 | 0人学习

CMake 与 Conan 集成实践
CMake 与 Conan 集成实践

共0课时 | 0人学习

Conan 2 高级依赖模型介绍
Conan 2 高级依赖模型介绍

共0课时 | 0人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn