算法面试(2)------休眠函数sleep_for和sleep_until

  • 操作系统:ubuntu22.04
  • IDE:Visual Studio Code
  • 编程语言:C++11

算法描述

这两个函数都定义在 头文件中,属于 std::this_thread 命名空间,用于让当前线程暂停执行一段时间。

函数功能
sleep_for(rel_time)让当前线程休眠一段相对时间(例如:休眠 100 毫秒)
sleep_until(abs_time)让当前线程休眠到某个绝对时间点(例如:休眠到 2025年9月15日中午12:00)

函数原型

#include <thread>
#include <chrono>// 1. 休眠一段相对时间
template <class Rep, class Period>
void std::this_thread::sleep_for(const std::chrono::duration<Rep, Period>& rel_time);// 2. 休眠到某个绝对时间点
template <class Clock, class Duration>
void std::this_thread::sleep_until(const std::chrono::time_point<Clock, Duration>& abs_time);

⚠️ 注意:如果传入负的 rel_time,sleep_for 的行为等同于不休眠(立即返回)。

sleep_for 详解:休眠一段相对时间

✅ 语法示例:

using namespace std::chrono;// 休眠 100 毫秒
std::this_thread::sleep_for(100ms);// 或者写成:
std::this_thread::sleep_for(milliseconds(100));
std::this_thread::sleep_for(seconds(1));        // 休眠 1 秒
std::this_thread::sleep_for(microseconds(500)); // 500 微秒

🧠 工作原理:

  • 当前线程调用 sleep_for 后,会进入阻塞状态(blocked)。
  • 操作系统将其从 CPU 调度队列中移除。
  • 经过指定时间后,操作系统将线程重新放入就绪队列,等待调度执行。
  • 线程恢复执行。

⚠️ 注意事项:

  • 实际休眠时间 ≥ 指定时间
    因为操作系统调度不是实时的,sleep_for 只保证“至少休眠这么长时间”,但可能更长(尤其在系统负载高时)。

  • 精度取决于系统和时钟
    通常系统时钟精度为 1~15 毫秒,所以 sleep_for(1us) 可能实际休眠 1ms。

  • 可被中断吗?
    在标准 C++ 中,不能被信号或外部事件中断(不像 POSIX 的 sleep())。一旦调用,必须等到时间结束。

使用场景
场景1:控制循环频率(如游戏主循环、传感器采样)

while (running) 
{read_sensor();process_data();std::this_thread::sleep_for(10ms); // 控制每 10ms 执行一次
}

场景2:重试机制中的退避策略(Retry with Backoff)

for (int i = 0; i < 3; ++i) 
{if (try_connect()) break;std::this_thread::sleep_for(std::chrono::milliseconds(100 * (i + 1))); // 递增等待
}

sleep_until 详解:休眠到某个绝对时间点

✅ 语法示例:

using namespace std::chrono;// 获取当前时间 + 2 秒
auto now = system_clock::now();
auto two_seconds_later = now + seconds(2);
std::this_thread::sleep_until(two_seconds_later);// 或者指定一个具体时间点(比如明天上午 9:00)
auto tomorrow = system_clock::now() + hours(24);
auto nine_am = std::chrono::time_point_cast<hours>(tomorrow);
nine_am += hours(9); // 假设今天是 0 点,加 9 小时
std::this_thread::sleep_until(nine_am);

🧠 工作原理:

  • sleep_until 接收一个 time_point 类型的时间点。
  • 线程会一直阻塞,直到系统时钟达到或超过该时间点。
  • 如果当前时间已经晚于或等于目标时间点,则 sleep_until 立即返回,不休眠。

✅ 使用场景
场景1:定时任务(如每天凌晨执行)

void run_daily_task_at_midnight() 
{while (true) {auto now = system_clock::now();auto tomorrow = system_clock::from_time_t(std::chrono::system_clock::to_time_t(now) + 86400); // 明天 00:00:00auto midnight = std::chrono::time_point_cast<seconds>(tomorrow);std::this_thread::sleep_until(midnight);perform_daily_backup();}
}

场景2:多个线程同步到同一时间点启动

auto start_time = std::chrono::system_clock::now() + std::chrono::seconds(5);// 所有线程都调用:
std::this_thread::sleep_until(start_time);
// 从而实现“5秒后同时开始”

💡 这比每个线程自己计算 sleep_for(5s) 更精确,避免了启动延迟累积误差。

sleep_for vs sleep_until 对比

特性sleep_forsleep_until
时间类型duration(持续时间)time_point(时间点)
语义“我要睡 5 秒”“我要睡到明天 9:00”
是否受系统时间调整影响是(如果系统时间被修改)
适合场景延迟、重试、节流定时任务、时间同步
若目标时间已过休眠指定时间立即返回(不休眠)

⚠️ 注意:sleep_until 使用的是 system_clock,如果用户手动调整了系统时间,可能导致线程提前唤醒或延迟唤醒。

如果需要更稳定的时钟,可使用 steady_clock(见下文)。

推荐使用 steady_clock 避免系统时间跳变

虽然 system_clock 是最常用的时钟,但它受系统时间调整(如 NTP 同步、手动修改)影响。

对于延迟控制类任务,建议使用 steady_clock,它是单调递增的,不会倒退。
示例:使用 steady_clock 的 sleep_until

auto start = std::chrono::steady_clock::now();
auto deadline = start + std::chrono::milliseconds(100);std::this_thread::sleep_until(deadline); // 推荐用于定时延迟
steady_clock 不受系统时间修改影响,更适合做超时、延迟等操作。

常见误区与注意事项

❌ 误区1:sleep_for(1ms) 一定能精确休眠 1ms

→ 错!受操作系统调度精度限制,实际可能休眠 1~15ms。
❌ 误区2:sleep_until 绝对可靠

→ 如果系统时间被手动调整或 NTP 校正,system_clock 时间点可能跳变,导致提前或延迟唤醒。
❌ 误区3:可以在任意线程调用

→ 可以,但注意:主线程调用也会阻塞整个程序。
✅ 最佳实践:

延迟控制 → 优先用 sleep_for + steady_clock
定时任务 → 用 sleep_until + system_clock
高精度需求 → 考虑使用平台特定 API(如 nanosleep on Linux)

完整示例代码

#include <iostream>
#include <thread>
#include <chrono>int main()
{using namespace std::chrono;std::cout << "Start: " << system_clock::now().time_since_epoch().count() << std::endl;// 1. sleep_for:休眠 2 秒std::cout << "Sleeping for 2s..." << std::endl;std::this_thread::sleep_for(seconds(2));// 2. sleep_until:休眠到 3 秒后auto target = steady_clock::now() + milliseconds(1500);std::cout << "Sleeping until steady time point..." << std::endl;std::this_thread::sleep_until(target);std::cout << "Done!" << std::endl;return 0;
}

总结

函数用途推荐时钟注意事项
sleep_for(duration)休眠一段相对时间steady_clock保证最小休眠时间
sleep_until(time_point)休眠到某个绝对时间system_clock受系统时间调整影响

✅ 一句话总结:

用 sleep_for 控制“延迟多久”,
用 sleep_until 控制“什么时候开始”。

它们是多线程中实现节流、重试、定时、同步启动等行为的基础工具,理解其差异和适用场景,能让你写出更健壮的并发程序。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/web/96834.shtml
繁体地址,请注明出处:http://hk.pswp.cn/web/96834.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

贪心算法应用:5G网络切片问题详解

Java中的贪心算法应用&#xff1a;5G网络切片问题详解 1. 5G网络切片问题概述 5G网络切片是将物理网络划分为多个虚拟网络的技术&#xff0c;每个切片可以满足不同业务需求&#xff08;如低延迟、高带宽等&#xff09;。网络切片资源分配问题可以抽象为一个典型的优化问题&…

Android WorkManager的概念和使用

1. WorkManager基础与核心概念 1.1 WorkManager概述 WorkManager是Android Jetpack架构组件库的核心成员&#xff0c;专为管理可靠的后台任务而设计。它提供了一套统一的API&#xff0c;用于调度需保障执行的延迟型异步任务&#xff08;如数据同步、日志上传&#xff09;&…

容器使用卷

1.创建一个卷并让容器挂载该卷1.创建一个卷[roothost1 ~]# docker volume create test-vol test-vol2.列出本地 Docker 主机上的卷[roothost1 ~]# docker volume ls DRIVER VOLUME NAME local test-vol3.查看该卷的详细信息[roothost1 ~]# docker volume inspect test-v…

高数基础知识(下)②

文章目录七、微分方程7.3 高阶线性微分方程7.3.1 线性微分方程的解的结构7.3.2 常系数齐次线性微分方程7.3.3 常系数非齐次线性微分方程八、多元函数微分学8.1 偏导数8.2 全微分8.3 基本定理8.4 复合函数微分法8.5 隐函数微分法8.6 多元函数的极值8.6.1 无条件极值8.6.2 条件极…

从0°到180°,STM32玩转MG996R舵机

1.MG996R舵机的性能参数参数数值产品型号MG995/MG996R产品重量55 g工作扭矩13 kgcm反应速度53-62 R/M使用温度-30C ~ 55C死区设置4 微秒插头类型JR、FUTABA 通用转动角度180&#xff08;左90&#xff0c;右90&#xff09;舵机类型数码舵机使用电压3.0 - 7.2 V工作电流100 mA结构…

[frontend]mermaid code2image

hello everyone, welcome to my bolg, here i will introduce something interesting, and if you are interested it, please just let me know. follow me and send me a message are both avaiable. what is mermaid? Mermaid 是一个工具&#xff0c;它能让你用简单的文字代…

Jakarta EE 在 IntelliJ IDEA 中开发简单留言板应用的实验指导(附完整代码)

Jakarta EE 在 IntelliJ IDEA 中开发简单留言板应用的实验指导(附完整代码) 摘要:实验基于Jakarta EE 9+(兼容Tomcat 10+)、Maven作为构建工具,并在IntelliJ IDEA 2023.2(Community版免费)中进行。项目使用Maven Archetype WebApp模板生成基础结构,然后升级到J…

JavaScript经典面试题一(JavaScript基础)

目录 一、JavaScript中的变量提升 1. 机制 2. 示例 3. 注意事项 4. 总结 二、var、let和const的区别。 1. 作用域&#xff08;Scope&#xff09; 2. 变量提升&#xff08;Hoisting&#xff09; 3. 重新赋值和重新声明 4. 示例 示例1&#xff1a;作用域和块级行为 示…

数据库造神计划第七天---增删改查(CRUD)(3)

&#x1f525;个人主页&#xff1a;寻星探路 &#x1f3ac;作者简介&#xff1a;Java研发方向学习者 &#x1f4d6;个人专栏&#xff1a;《从青铜到王者&#xff0c;就差这讲数据结构&#xff01;&#xff01;&#xff01;》、 《JAVA&#xff08;SE&#xff09;----如此简单&a…

AWS SQS 可观测性最佳实践

AWS SQS AWS SQS&#xff08;Amazon Simple Queue Service&#xff09;是一种完全托管的消息队列服务&#xff0c;用于在分布式系统中解耦和缓冲消息。它支持高可用性、可扩展性和安全性&#xff0c;能够处理大量消息&#xff0c;确保消息的可靠传输和顺序性。开发者可以轻松集…

AI推理范式:从CoT到ReAct再到ToT的进化之路

在人工智能领域&#xff0c;如何让模型像人类一样进行复杂推理和问题解决&#xff0c;一直是核心挑战。近年来&#xff0c;思维链&#xff08;Chain-of-Thought, CoT&#xff09;、推理与行动&#xff08;ReAct&#xff09; 和 思维树&#xff08;Tree-of-Thoughts, ToT&#x…

2025时序数据库选型:深入解析IoTDB从主从架构基因到AI赋能的创新之路

原创经验总结,拒绝空谈,用数据和实战说话 时序数据时代的"四重考验" 在智慧工厂、新能源车、金融市场等场景中,每秒百万级的数据点如潮水般涌来。这些时序数据背后隐藏着四大核心挑战:极高的写入并发、强时间关联性查询、海量数据生命周期管理,以及乱序与高基…

深入浅出LVS负载均衡群集:原理、分类与NAT模式实战部署

深入浅出LVS负载均衡群集&#xff1a;原理、分类与NAT模式实战部署 文章目录深入浅出LVS负载均衡群集&#xff1a;原理、分类与NAT模式实战部署一、企业群集&#xff1a;从单台服务器到分布式架构的必然选择1. 什么是群集&#xff1f;2. 为什么需要群集&#xff1f;二、企业群集…

Flash Table实测:JAI赋能低代码开发,重塑企业级应用构建范式

目录&#x1f50d; 引言1.1 什么是Flash Table1.2 低代码平台的进化与FlashTable的革新✨FlashTable背景&#xff1a;为什么需要新一代低代码平台&#xff1f;2.1 传统开发的痛点2.2 低代码平台的局限2.3 FlashTable的差异化定位&#x1f4bb; FlashTable安装&#xff1a;Docke…

SonarQube代码质量管理平台本地化搭建和使用

SonarQube 是一个开源的代码质量管理平台&#xff0c;主要用于持续检查代码质量&#xff0c;支持多种编程语言。 本文章记录了在windows环境中&#xff0c;搭建和使用SonarQube的完整过程。 ①SonarQube平台搭建 SonarQube最新社区版本下载地址&#xff1a; https://www.son…

基于双向LSTM深度学习网络模型的文本序列推荐系统matlab仿真

目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.部分程序 4.算法理论概述 5.完整程序 1.程序功能描述 在信息爆炸的时代&#xff0c;用户面临着海量文本信息的筛选难题&#xff0c;文本序列推荐系统应运而生。双向长短期记忆网络&#xff08;Bi-directional Long …

Transformer实战(17)——微调Transformer语言模型进行多标签文本分类

Transformer实战(17)——微调Transformer语言模型进行多标签文本分类 0. 前言 1. 多标签文本分类 2. 数据加载与处理 3. 模型微调 小结 系列链接 0. 前言 与单标签分类不同,多标签分类要求模型能够为同一文本分配多个相关标签,这在新闻分类、文献标注、内容推荐等场景中尤…

开源 C++ QT Widget 开发(十六)程序发布

文章的目的为了记录使用C 进行QT Widget 开发学习的经历。临时学习&#xff0c;完成app的开发。开发流程和要点有些记忆模糊&#xff0c;赶紧记录&#xff0c;防止忘记。 相关链接&#xff1a; 开源 C QT Widget 开发&#xff08;一&#xff09;工程文件结构-CSDN博客 开源…

MATLAB2-结构化编程和自定义函数-台大郭彦甫视频

目录 if elseif else switch case otherwise while exercise练习 for 预宣告 练习题 break tips编程的小技巧 functions函数 练习题 函数句柄 if elseif else 如果condition为真&#xff0c;执行语句 if condition1statement1 elseif condition2statement2 elsest…

LVGL移植2048小游戏全攻略

目录 准备脚手架 修改源码 对接触摸 测试编译 测试运行 这一节将以一个已经编写好的 lvgl 小游戏 2048 描述如何将已经编写完成的 lvgl 程序移植到开发板上。 准备脚手架 在这之前&#xff0c;我们先准备基础的 LVGL 脚手架。可以直接从 lv_g2d_test 里复制过来进行修改…