Skip to content

Commit bdea4f4

Browse files
committed
完成 std::this_thread 命名空间内容的讲解介绍
1 parent ba7b881 commit bdea4f4

File tree

2 files changed

+89
-1
lines changed

2 files changed

+89
-1
lines changed

md/02使用thread.md

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -438,3 +438,91 @@ void test(){
438438
t.detach();
439439
}
440440
```
441+
442+
### `std::this_thread`
443+
444+
这个命名空间包含了管理当前线程的函数。
445+
446+
1. [`yield`](https://zh.cppreference.com/w/cpp/thread/yield) 建议实现重新调度各执行线程。
447+
2. [`get_id`](https://zh.cppreference.com/w/cpp/thread/get_id) 返回当前线程 id。
448+
3. [`sleep_for`](https://zh.cppreference.com/w/cpp/thread/sleep_for) 使当前线程停止执行指定时间。
449+
4. [`sleep_until`](https://zh.cppreference.com/w/cpp/thread/sleep_until) 使当前线程执行**停止到**指定的时间点。
450+
451+
它们之中最常用的是 `get_id`,其次是 `sleep_for`,再然后 `yield``sleep_until` 较少。
452+
453+
- 使用 `get_jd` [打印](https://godbolt.org/z/fPcaj7xTv)主线程和子线程的 ID。
454+
455+
```cpp
456+
int main() {
457+
std::cout << std::this_thread::get_id() << '\n';
458+
459+
std::thread t{ [] {
460+
std::cout << std::this_thread::get_id() << '\n';
461+
} };
462+
t.join();
463+
}
464+
```
465+
466+
- 使用 `slee_for` 延时。当 `Sleep` 之类的就行,但是它需要接受的参数不同,是 `std::chrono` 命名空间中的时间对象。
467+
468+
```cpp
469+
int main() {
470+
std::this_thread::sleep_for(std::chrono::seconds(3));
471+
}
472+
```
473+
474+
主线程延时 3 秒,这个传入了一个临时对象 `seconds` ,它是模板 [`std::chrono::duration`](https://zh.cppreference.com/w/cpp/chrono/duration) 的别名,以及还有很多其他的时间类型,都基于这个类。说实话挺麻烦的,如果您支持 C++14,建议使用[时间字面量](https://zh.cppreference.com/w/cpp/symbol_index/chrono_literals),在 [`std::chrono_literals`](https://github.com/microsoft/STL/blob/main/stl/inc/__msvc_chrono.hpp#L742-L804) 命名空间中。我们可以改成下面这样:
475+
476+
```cpp
477+
using namespace std::chrono_literals;
478+
479+
int main() {
480+
std::this_thread::sleep_for(3s);
481+
}
482+
```
483+
484+
简单直观。
485+
486+
- `yield` 减少 CPU 的占用。
487+
488+
```cpp
489+
while (!isDone()){
490+
std::this_thread::yield();
491+
}
492+
```
493+
494+
线程需要等待某个操作完成,如果你直接用一个循环不断判断这个操作是否完成就会使得这个线程占满 CPU 时间,这会造成资源浪费。此时可以判断操作是否完成,如果还没完成就调用 yield 交出 CPU 时间片让其他线程执行,过一会儿再来判断是否完成,这样这个线程占用 CPU 时间会大大减少。
495+
496+
- 使用 `sleep_until` 让当前线程延迟到具体的时间。我们延时 5 秒就是。
497+
498+
```cpp
499+
int main() {
500+
// 获取当前时间点
501+
auto now = std::chrono::system_clock::now();
502+
503+
// 设置要等待的时间点为当前时间点之后的5秒
504+
auto wakeup_time = now + 5s;
505+
506+
// 输出当前时间
507+
auto now_time = std::chrono::system_clock::to_time_t(now);
508+
std::cout << "Current time:\t\t" << std::put_time(std::localtime(&now_time), "%H:%M:%S") << std::endl;
509+
510+
// 输出等待的时间点
511+
auto wakeup_time_time = std::chrono::system_clock::to_time_t(wakeup_time);
512+
std::cout << "Waiting until:\t\t" << std::put_time(std::localtime(&wakeup_time_time), "%H:%M:%S") << std::endl;
513+
514+
// 等待到指定的时间点
515+
std::this_thread::sleep_until(wakeup_time);
516+
517+
// 输出等待结束后的时间
518+
now = std::chrono::system_clock::now();
519+
now_time = std::chrono::system_clock::to_time_t(now);
520+
std::cout << "Time after waiting:\t" << std::put_time(std::localtime(&now_time), "%H:%M:%S") << std::endl;
521+
}
522+
```
523+
524+
`sleep_until` 本身设置很简单,是打印时间格式之类的,设置时区麻烦。[运行结果](https://godbolt.org/z/4qYGbcvYW)。
525+
526+
介绍了一下 `std::this_thread` 命名空间中的四个成员函数的基本用法,我们后续会经常看到这些函数的使用,不用着急。
527+
528+
### `std::thread` 转移所有权

md/详细分析/01thread的构造与源码解析.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ void _Start(_Fn&& _Fx, _Args&&... _Ax) {
9797

9898
3. `auto _Decay_copied = _STD make_unique<_Tuple>(_STD forward<_Fn>(_Fx), _STD forward<_Args>(_Ax)...)`
9999

100-
- 使用 [`make_unique`](https://zh.cppreference.com/w/cpp/memory/unique_ptr/make_unique) 创建了一个独占指针,指向的是 `_Tuple` 类型的对象,存储了传入的函数对象和参数的副本。
100+
- 使用 [`make_unique`](https://zh.cppreference.com/w/cpp/memory/unique_ptr/make_unique) 创建了一个独占指针,指向的是 `_Tuple` 类型的对象,**存储了传入的函数对象和参数的副本**
101101

102102
4. `constexpr auto _Invoker_proc = _Get_invoke<_Tuple>(make_index_sequence<1 + sizeof...(_Args)>{})`
103103

0 commit comments

Comments
 (0)