std::this_thread::sleep_for仅适用于单次阻塞等待,非真正定时器;SimpleTimer类通过独立线程+condition_variable实现可取消一次性定时;必须使用steady_clock计时;多定时任务应共用线程池+优先队列。

std::this_thread::sleep_for 适合短时等待但不是真定时器
它只是让当前线程暂停指定时间,无法在到期时自动触发回调,也不支持重复执行。用错场景容易导致主线程卡死或逻辑混乱。
常见错误现象:std::this_thread::sleep_for 被塞进循环里做“轮询式定时”,CPU 占用高、精度差、难以取消。
- 仅适用于“我只想等 100ms 再继续往下走”这种单次阻塞需求
- 不能跨线程通知,无法解耦任务与等待逻辑
- 没有超时控制机制,
sleep_for期间无法响应外部中断(如停止信号)
std::thread + std::chrono 实现可取消的一次性定时器
核心思路:起一个独立线程,等待指定时长后执行回调;提供 cancel() 方法通过原子变量中断等待。
class SimpleTimer {
std::atomic<bool> cancelled_{false};
std::thread t_;
<p>public:
template<typename f typename... args>
SimpleTimer(std::chrono::milliseconds delay, F&& f, Args&&... args) {
t_ = std::thread([d = delay, cb = std::forward<f>(f),
tup = std::make<em>tuple(std::forward<args>(args)...),
&cancelled = cancelled</args></em>] {
if (std::cv_status::no_timeout ==
std::condition_variable{}.wait_for(
std::unique_lock<:mutex>{}, d)) {
if (!cancelled) std::apply(cb, tup);
}
});
}</:mutex></f></typename></p>
<pre class="brush:php;toolbar:false;">void cancel() { cancelled_ = true; }
~SimpleTimer() { if (t_.joinable()) t_.join(); }
};
注意点:
-
std::condition_variable::wait_for可被虚假唤醒,必须配合cancelled_检查 - 不要直接传引用到线程里,用
std::make_tuple+std::apply安全转移参数 - 析构必须
join(),否则程序异常终止
std::chrono::steady_clock 是唯一推荐的计时基准
不用 system_clock,它可能因系统时间调整跳变;也不用 high_resolution_clock,它不保证单调性。只有 steady_clock 能保证“流逝时间 = 真实经过时间”。
典型误用:
- 写
auto start = system_clock::now(),然后if (now() - start > X)—— 时间回拨会让条件永远不成立 - 用
high_resolution_clock::now()做超时判断 —— 某些平台该钟可能随 CPU 频率缩放而跳变
正确做法始终是:
auto start = std::chrono::steady_clock::now(); // ... auto elapsed = std::chrono::steady_clock::now() - start;
多个定时任务共用一个线程池更高效
每个定时器都开线程资源浪费大,且难管理。改用单个后台线程 + 优先队列(按触发时间排序),每次取最近到期任务执行。
关键结构:
- 用
std::priority_queue存std::pair<expire_time callback></expire_time>,自定义比较器 - 主线程调用
post(delay, cb)插入任务,后台线程用wait_until等待队首 - 插入新任务时需 notify 条件变量,唤醒等待中的线程重新计算等待时长
这个模型接近 boost::asio::io_context 的定时器实现逻辑,但去掉依赖后可控性更强。真正复杂场景建议直接用 asio 或 libuv,自己手写容易漏掉唤醒竞争、过期任务清理等边界。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











