#define _CRT_SECURE_NO_WARNINGS
// 之前介绍的所有阻塞调用都会无限期地阻塞,直到等待的事件发生,线程才会被唤醒。但在某些情况下,可能希望设置一个等待时间的限制。
#include <iostream>
#include<thread>
#include<mutex>
#include<chrono>
#include <iomanip>
#include <future>
#include<condition_variable>
//对于C++标准库而已,时钟提供四种信息:当前时间、时间点类型、时钟tick周期、是否为稳定时钟]
//特定时钟的时间点类型由 time_point 成员类型定义,因此 some_clock::now() 的返回类型是 some_clock::time_point
void Test1() {
//通过调用静态成员函数now可以返回系统当前的时间
//系统时钟
std::chrono::system_clock::time_point time = std::chrono::system_clock::now(); //返回值,可以用auto缩短
std::time_t now_c = std::chrono::system_clock::to_time_t(time); //把tim转为time_t类型
//std::localtime(&now_c) 将 std::time_t 格式的时间转换为 struct tm* 结构体,以便后续用于格式化。
std::cout << "当前时间为:" << std::put_time(std::localtime(&now_c), "%Y-%m-%d %X")<<"\n"; //格式化
//查看系统时钟是否是稳定的
bool isSteady = std::chrono::system_clock::is_steady;
std::cout << "系统时钟是否稳定: " << (isSteady ? "是" : "否") << "\n";
//除了系统时钟,chrono库内还有很多时钟
//查看steady_clock时钟是否是稳定的
isSteady = std::chrono::steady_clock::is_steady;
std::cout << "稳定时钟是否稳定: " << (isSteady ? "是" : "否") << "\n";
//查看high_resolution_clock时钟是否是稳定的
isSteady = std::chrono::high_resolution_clock::is_steady;
std::cout << "高精度时钟是否稳定: " << (isSteady ? "是" : "否") << "\n";
}
//std::chrono::duration 是一个模板类,使用时需要指定两个模板参数:
//第一个参数是表示时间长度的数据类型(通常是整数类型,如 int, long, std::chrono::seconds::rep 等)。
//第二个参数是时间单位,可以是 std::ratio 类型(如 std::ratio<1> 表示一秒,std::milli 表示一毫秒等)。
void Test2() {
//准库中预定义了多种时长别名,如nano、milli、microseconds等,方便用户快速使用。
//定义一个1s秒持续时间
std::chrono::duration<int,std::nano> du1(1); //第二个参数不定义的话,默认为秒
std::cout << "秒:" << du1.count() << "\n";
//定义一个500ms的时间
std::chrono::duration <double>du2(0.5); //仍然使用秒
std::cout << "秒:" << du2.count() << "\n";
std::chrono::duration<int, std::milli>du3(500); //直接使用毫秒
std::cout << "毫秒:" << du3.count() << "\n";
//定义一个100微秒的时间
std::chrono::duration <int,std::micro>du7(100);
std::cout << "微秒:" << du7.count() << "\n";
//std::chrono::duration重载了+-运算符和比较运算符
std::chrono::duration<double,std::milli> du4 = du2 + du3; //毫秒+秒 = 输出为毫秒
std::cout << "du4毫秒:" << du4.count() << "\n";
auto du5 = du2 - du1;//秒-秒 =(输出)秒
std::cout << "du5秒:" << du5.count() << "\n";
//使用std::ratio的比率来定义时间单位
std::chrono::duration<int, std::ratio<1, 1000>>d(10); //这里1/1000s =1ms
std::cout << "毫秒:" << d.count() << "\n";
std::chrono::duration<int, std::ratio<60, 1>>d2(5); //这里60/1 = 60s=1min
std::cout << "分钟:" << d2.count() << "\n";
bool flag1 = du4 > du5;
std::cout << "du4>du5:"<<flag1 << "\n";
bool flag2 = du2 == du1;
std::cout << "du2==du1:" << flag2 << "\n";
//两个clock_point相减得到一个duration
std::chrono::steady_clock::time_point start = std::chrono::steady_clock::now();
std::this_thread::sleep_for(std::chrono::seconds(1)); //休眠1s
std::chrono::steady_clock::time_point end = std::chrono::steady_clock::now();
std::chrono::duration<double,std::milli> elapsed_time = end - start;//这里相减返回一个duration
std::cout << "持续了" << elapsed_time.count() << "ms\n";
}
void Test3() {
//为了方便C++14引入了 std::chrono_literals 命名空间,提供了许多预定义字面量后缀
using namespace std::chrono_literals;
//这里可以直接使用
auto one_day = 24h;
auto half_an_hour = 30min;
auto thirty_second = 30s;
//避免了很长的前缀
std::chrono::duration<double, std::ratio<60, 1>> minute(30);
//又或者避免了使用std::nanosecond,本质上nanosecond也是预先使用using语句换名的,所以本质上是一样的
std::chrono::nanoseconds second(30);
std::cout << "秒:" << second.count() << " == " << thirty_second.count() << "\n";
std::cout << "分钟:" << minute.count() << " == " << half_an_hour.count() << "\n";
//可以使用std::chrono::duration_cast<>进行显示的类型转换
std::chrono::milliseconds ms(54802);
std::chrono::seconds s = std::chrono::duration_cast<std::chrono::seconds>(ms);//这里会截断
std::cout << "54802ms = " << s.count() << "s" << "\n";
}
//基于持续时间的等待
void do_something() {
std::cout << "进行其他任务\n";
}
void time_out() {
std::cout << "超时了!进行超时的任务\n";
}
void delay_task() {
std::cout << "任务被延迟!进行延迟的任务\n";
}
void wait_something() {
std::this_thread::sleep_for(std::chrono::seconds(1));
}
void Test4() {
auto f = std::async(wait_something);
//任务延迟
// auto f = std::async(std::launch::deferred,wait_something);
//wait_for返回一个future_status
// wait_for如果等待超时,则返回 std::future_status::timeout;
//如果期值已准备好,则返回 std::future_status::ready;
//如果期值的任务被推迟,则返回 std::future_status::deferred。
//std::future_status status = f.wait_for(std::chrono::milliseconds(500));//最多等0.5s
std::future_status status = f.wait_for(std::chrono::seconds(2));//最多等2s
if (status == std::future_status::ready) {
do_something();
}
else if (status == std::future_status::timeout) {
time_out();
}
else { //任务被延迟
delay_task();
}
}
//时钟的时间点由 std::chrono::time_point<> 类模板的实例表示
//std::chrono::time_point<std::chrono::system_clock, std::chrono::minutes>第一个参数是时钟类型,第二个参数是时钟单位(一般是秒或更小)
void calculate() {
std::this_thread::sleep_for(std::chrono::seconds(1));
}
void Test5() {
//系统时间点
std::chrono::system_clock::time_point start =std::chrono::system_clock::now(); //获取当前时间点
calculate();
auto end = std::chrono::system_clock::now();
auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(end - start); //单位是微秒
std::cout << "系统时钟:caculate函数花费了:" << duration.count()<< "ms 的时间\n"; //单位是微秒
//稳定时间点
std::chrono::steady_clock::time_point st = std::chrono::high_resolution_clock::now();
calculate();
auto ed = std::chrono::steady_clock::now();
auto d = std::chrono::duration_cast<std::chrono::milliseconds>(ed-st);
std::cout << "稳定时钟:caculate函数花费了:" << d.count() << "ms 的时间\n"; //单位是微秒
//最高精度时间点
std::chrono::high_resolution_clock::time_point begin= std::chrono::high_resolution_clock::now();
calculate();
auto over = std::chrono::high_resolution_clock::now();
auto du = std::chrono::duration_cast<std::chrono::milliseconds>(over - begin);
std::cout << "高精度时钟:caculate函数花费了:" << du.count() << "ms 的时间\n"; //单位是微秒
}
std::condition_variable cv; //条件变量,用于唤醒线程
bool done; //设置完成标签,如果完成了就填充为true
std::mutex m; //互斥锁,和条件变量配合使用
void do_work() {
std::lock_guard lk(m); //上锁
std::this_thread::sleep_for(std::chrono::milliseconds(800)); //模拟时间
std::cout << "事件执行完毕!\n";
done = true;
cv.notify_one(); //提醒线程
}
bool wait_loop() {
auto const timeout = std::chrono::steady_clock::now() + std::chrono::milliseconds(500); //最多等待500ms
bool flag = true;
std::unique_lock lk(m);
while (!done) { //不断检查,直到任务完成或超时
if (cv.wait_until(lk, timeout) == std::cv_status::timeout) { //如果时间到了的话
flag = false;
break;
}
}
return flag; //查看是否超时
}
void Test6() {
std::thread t1(do_work);
if (wait_loop()) {
std::cout << "未超时!\n";
}
else {
std::cout << "超时!\n";
}
t1.join();
}
//这里补充一下this_thread::sleep_until的用法
void Test7() {
//std::this_thread::sleep_until接受一个时间点time_point
auto start = std::chrono::system_clock::now();
std::time_t now_c = std::chrono::system_clock::to_time_t(start+ std::chrono::seconds(2)); //把tim转为time_t类型
std::cout << "休眠直至到时间:" << std::put_time(std::localtime(&now_c), "%Y-%m-%d %X") << "为止\n";
std::this_thread::sleep_until(start + std::chrono::seconds(2)); //睡眠直到某个时间点
std::cout << "线程被唤醒!执行任务\n";\
}
int main(){
//Test1();
// Test2();
// Test3();
//Test4();
//Test5();
//Test6();
Test7();
}