本文简要介绍C++标准库提供的几种线程操作方法,主要介绍如何判断线程是否已经结束运行。

一、std::thread

std::thread 未提供判断线程是否结束的方法。

如果线程未进行 detach 且此时该线程处于 joinable 状态,析构该线程对象会触发异常。

线程处于 joinable 状态不代表线程正在执行,joinable 状态仅代表线程是可执行的,下面几种情况下线程会处于非 joinable 状态:

  • 使用缺省构造函数构造的 std::thread 对象。
  • 该线程对象的所有权已被 move 给其他对象。
  • 该线程对象已经调用过 join 或 detach 函数。

由此可见,即便线程已经执行完成,只要未调用过 join 方法,线程仍然是 joinable 状态。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <iostream>
#include <thread>

std::thread Thread1() {
std::thread t = std::thread([]() {
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
});
return t;
}

int main()
{
std::thread t1 = Thread1();
t1.join(); //等待线程结束

std::thread t2 = std::thread([]() {
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
});

std::cout << "thread id:" << t2.get_id() << std::endl;
std::cout << "joinable:" << t2.joinable() << std::endl; // 1
t2.detach();
std::cout << "joinable:" << t2.joinable() << std::endl; // 0

std::this_thread::sleep_for(std::chrono::milliseconds(2000));

return 0;
}

二、std::async

通过std::async可以判断线程是否结束运行。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <iostream>
#include <future>

int main()
{
std::future<void> f = std::async(std::launch::async, []() {
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
});

bool isRunning = f.valid() && f.wait_for(std::chrono::milliseconds(0)) == std::future_status::timeout;

std::cout << isRunning << std::endl;

f.wait();

isRunning = f.valid() && f.wait_for(std::chrono::milliseconds(0)) == std::future_status::timeout;

std::cout << isRunning << std::endl;

return 0;
}

2.1 判断 std::future 是否结束

1
2
bool isRunning = f.valid() &&
f.wait_for(std::chrono::milliseconds(0)) == std::future_status::timeout;

2.2 std::shared_future

std::future不支持赋值构造,需要使用std::shared_future

1
2
3
4
5
std::shared_future<void> f1 = std::async(std::launch::async, []() {
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
});

std::shared_future<void> f2 = f1;