- 创建线程对象:
//无参构造,该线程对象没有关联任何线程函数,也就是它没有启动任何线程:
thread t1;
//...
t1 = thread(func, 10);//移动构造(调用移动赋值函数)
t1.join();
//含参构造
thread t1(func1, 1, 10);
//thread 提供了移动构造函数,能够用一个右值线程对象来构造一个线程对象,以下两种都是 移动构造:
thread t3 = thread(func, 4, 20); // 创建匿名函数对象,赋值给 t3 (调用移动赋值函数)
thread t4(std::move(thread(func, 10, 20))); // 显式move (调用移动构造函数)
-
成员函数:
join和detach都用于回收线程资源
-
join 函数
-
功能是 连接一个已经终止的线程,并回收它的资源(调用一次,只能回收一个线程)。
-
阻塞函数:调用它的线程会一直阻塞,直到 对应的线程终止 并被 join 函数回收,原线程才会继续执行。
-
任意一个线程都可以使用 join 来回收其他线程,但一般在主线程中使用
-
-
#include <iostream>
#include <thread>
using namespace std;
void func()
{
for(int i = -10; i > -20; i--)
{
cout << "from func():" << i << endl;
}
}
int main() //主线程
{
thread t(func); //子线程
t.join(); //等待子线程结束后才进入主线程
cout << "mian()" << endl;
cout << "mian()" << endl;
cout << "mian()" << endl;
return 0;
}
-
detach函数
-
功能是 分离一个线程,也就是当 调用detach的线程对象终止时,它的资源会自动 被系统回收,而不是被其他线程回收。
-
非阻塞地回收线程
-
#include <iostream>
#include <thread>
using namespace std;
void func()
{
for(int i = -10; i > -20; i--)
{
cout << "from func():" << i << endl;
}
}
int main() //主线程
{
cout << "mian()" << endl;
cout << "mian()" << endl;
cout << "mian()" << endl;
thread t(func); //子线程
t.detach(); //分离子线程,让系统自动回收
return 0;
}
-
joinable函数:
- bool类型函数,它会表示当前的线程是否是可执行线程(能被join或者detach)
- 1 -> 表示可以join或者detach
- 0 -> 表示已经可以join或者detach,不可再重复回收了
- 可以通过 joinable()函数 判断线程是否是有效的,如果是以下任意情况,则线程无效:
- 线程对象没有关联函数
- 线程对象的状态已经转移给其他线程对象
- 线程已经调用join 或者detach结束
- bool类型函数,它会表示当前的线程是否是可执行线程(能被join或者detach)
- 创建线程对象后,如果向启动线程的话,必须要提供线程关联函数。线程函数一般情况下可按照以下四种方式提供:
- 函数指针
- lambda表达式
- 函数对象
- 包装器(function)
void ThreadFunc(int a) {
cout << "Thread1" << a << endl;
}
void T()
{
cout << "hello" << endl;
}
class TF
{
public:
void TT()
{
cout << "NI" << endl;
}
void operator()()
{
cout << "Thread3" << endl;
}
};
int main()
{
// 线程函数为函数指针
thread t1(ThreadFunc, 10);
// 线程函数为lambda表达式
thread t2([] {cout << "Thread2" << endl; });
// 线程函数为函数对象
TF tf;
thread t3(tf);
thread t5(&TF::TT, TF());
//线程函数为包装器
function<void()> t = T;
thread t4(t);
t1.join();
t2.join();
t3.join();
t4.join();
t5.join();
cout << "Main thread!" << endl;
return 0;
}
-
禁止拷贝线程对象:thread类 不允许拷贝构造以及赋值,但是可以移动构造和移动赋值,即一个线程对象关联的 线程的状态 转移给 其他线程对象,转移期间不影响线程的执行
-
线程函数参数
- 线程函数的参数是以 值拷贝 的方式 拷贝到线程栈空间中的,实际引用的是 线程栈中的拷贝,而不是外部实参。所以,即使参数是引用类型,最后也不能把改变后的结果带到外面。
- 注意:如果线程参数是类成员函数时,必须将this作为线程函数参数