c++11开始 STL 提供了 sleep_for 及 sleep_until 用于休眠, 来理理。
1. 文档
1.1 std::this_thread::sleep_for
//(c++11起)
//include <thread>
template< class Rep, class Period >
void sleep_for( const std::chrono::duration );
阻塞当前线程执行,至少经过指定的 sleep_duration 。
此函数可能阻塞长于 sleep_duration ,因为调度或资源争议延迟。
标准库建议用稳定时钟度量时长。若实现用系统时间代替,则等待时间亦可能对时钟调节敏感。
参数
sleep_duration 要睡眠的时长
异常
任何时钟、 time_point 或 duration 在执行间抛出的异常(标准库提供的时钟、时间点和时长决不抛出)。
示例
#include <iostream>
#include <chrono>
#include <thread>
int main()
{
using namespace std::chrono_literals;
std::cout << "Hello waiter\n" << std::flush;
auto start = std::chrono::high_resolution_clock::now();
std::this_thread::sleep_for(2000ms);
auto end = std::chrono::high_resolution_clock::now();
std::chrono::duration<double, std::milli> elapsed = end-start;
std::cout << "Waited " << elapsed.count() << " ms\n";
}
可能的输出:
Hello waiter
Waited 2000.12 ms
1.2 std::this_thread::sleep_until
//(c++11起)
//include <thread>
template< class Clock, class Duration >
void sleep_until( const std::chrono::time_point<Clock,Duration>& sleep_time );
阻塞当前线程,直至抵达指定的 sleep_time 。
Clock 必须符合时钟 (Clock) 要求。如果 std::chrono::is_clock_v<Clock> 是 false,那么程序非良构。 (C++20 起)
标准推荐使用绑定到 sleep_time 的时钟,此时调整时钟会有影响。从而阻塞的时长可能会小于或大于调用时的 sleep_time - Clock::now(),取决于调整的方向以及实现是否尊重这样的调整。函数也可能会因为调度或资源纠纷延迟而阻塞到 sleep_time 之后的某个时间点。
参数
sleep_time 要阻塞到的时间
异常
任何 Clock 或 Duration 可能抛出的异常(标准库提供的时钟和时长决不抛出)
示例
#include <iostream>
#include <chrono>
#include <thread>
int main() {
// 获取当前时间点
auto now = std::chrono::system_clock::now();
// 设置线程休眠到未来的某个时间点,例如5秒后
auto five_seconds_future = now + std::chrono::seconds(5);
// 使线程休眠直到指定的时间点
std::this_thread::sleep_until(five_seconds_future);
// 当线程醒来后,输出消息
std::cout << "Woke up after 5 seconds!" << std::endl;
return 0;
}
输出:
Woke up after 5 seconds!
1.3 系统 API
1.3.1 Linux
- usleep
#include <unistd.h>
usleep(unsigned int usecs);
使调用线程睡眠指定的微秒数。这个函数是UNIX和Linux中传统的延迟方法,但由于其精度问题,现在通常被更精确的函数所替代。
- nanosleep
#include <time.h> int nanosleep(const struct timespec *req, struct timespec *rem);
提供了纳秒级的精度,允许你指定一个timespec结构来表示要睡眠的时间。
- clock_nanosleep
#include <time.h>
int clock_nanosleep(clockid_t clock_id, int flags,
const struct timespec *req,
struct timespec *rem);
允许你基于特定的时钟(如实时时钟或单调时钟)进行睡眠。它提供了更高的精度和灵活性。
1.3.2 Windows
- Sleep
#include <windows.h>
void Sleep(DWORD dwMilliseconds);
它使当前线程暂停执行指定的毫秒数。
- SleepEx
DWORD SleepEx(DWORD dwMilliseconds, BOOL bAlertable);
SleepEx是Sleep的扩展版本,它提供了更多的选项,比如允许线程在休眠期间接收信号。
2. 实现
- linux gcc
- windows vs2022
_Thrd_sleep没有找到相应的说明。
测试现象:如果在休眠时,把系统时间向回调10分钟,那么它会相应的卡在_Thrd_sleep里面多10分钟, 与设想的不一样(小心!!!)。
- 总结:
通过上面的文档及源码可知:
多使用sleep_for, 少使用sleep_until。
不要一次休眠太长时间, 如:要休眠120秒, 那么可以换成休眠120次, 每次休眠1秒。
尽量避免因调整系统时间引起问题。
示例
#include <iostream>
#include <thread>
#include <chrono>
int main()
{
std::cout << "go to sleep" << std::endl;
std::thread([]() {
std::cout << "std::this_thread::sleep_for" << std::endl;
auto sec = std::chrono::seconds(3);
std::this_thread::sleep_for(sec);
}).join();
std::thread([]() {
std::cout << "std::this_thread::sleep_until" << std::endl;
auto now = std::chrono::system_clock::now();
now += std::chrono::seconds(3);
std::this_thread::sleep_until(now);
}).join();
std::cout << "all wakeup" << std::endl;
return 0;
}