thread创建线程三种方式、join、detach关键字
通过函数创建一个线程
先上代码
#include <iostream>
#include <thread>
using namespace std;
void mythread()
{
cout << "我是子线程,执行完毕!\n"<<endl;
}
int main()
{
//thread+线程对象名(函数名)创建线程
thread mthread(mythread);
mthread.join();
cout << "我是主线程,已经执行完毕!\n";
return 0;
}
执行结果
一个线程就是干一件事,那么就需要有一个执行函数,mythread()就是执行函数,功能就是输出一句话。join关键字的作用就是阻塞主线程,等待子线程结束之后,在回来继续执行主线程。若不加jion()关键字,就会出现运行报错,主线程和子线程随机切换执行的情况。
datach()
一般情况来说,在主线程的结束之后,子线程就会被强制结束。特殊的可以用detach关键字,将子线程的管理权从主线程转变到运行时库。这样主线程和子线程分离,主线程结束之后,不会影响子线程继续执行(子线程转入后台执行,由运行时库清理相关资源)
代码
#include <iostream>
#include <thread>
using namespace std;
void mythread()
{
cout << "我是子线程a!\n"<<endl;
cout << "我是子线程b!\n" << endl;
cout << "我是子线程c!\n" << endl;
cout << "我是子线程d!\n" << endl;
cout << "我是子线程e!\n" << endl;
cout << "我是子线程f!\n" << endl;
cout << "我是子线程g!\n" << endl;
cout << "我是子线程h!\n" << endl;
}
int main()
{
thread mthread(mythread);
//mthread.join();
mthread.detach();
cout << "我是主线程1!\n";
cout << "我是主线程2!\n";
//让主线程休眠200毫秒,否则主线程进行太子线程还没轮上,打印窗口就关闭了
//打印窗口是跟着主线程一块的,主线程退出,窗口就退出
std::this_thread::sleep_for(std::chrono::milliseconds(200));
cout << "我是主线程3!\n";
cout << "我是主线程4!\n";
cout << "我是主线程5!\n";
cout << "我是主线程6!\n";
return 0;
}
结果
joinable()
要注意,对一个线程,join和detach只能用一次,不能同时使用否则会运行异常。可以通过joinable()判读程序是否可以join或者detach,若可以咋返回true否则返回false;
代码
#include <iostream>
#include <thread>
using namespace std;
void mythread()
{
cout << "我是子线程a!\n"<<endl;
}
int main()
{
thread mthread(mythread);
//mthread.join();
cout << "joinable值为:" << mthread.joinable() << endl;
mthread.detach();
cout << "joinable值为:" << mthread.joinable() << endl;
cout << "我是主线程1!\n";
return 0;
}
结果
通过类创建一个线程
代码如下
#include <iostream>
#include <thread>
using namespace std;
class Lei
{
public:
int m_i;
Lei(int& i) :m_i(i)
{
cout << "lei构造函数被执行" << endl;
}
Lei(const Lei& lei) :m_i(lei.m_i)
{
cout << "lei拷贝构造函数被执行" << endl;
}
~Lei()
{
cout << "lei析构函数被执行" << endl;
}
//执行类的功能
void operator()()
{
cout << "operator()函数被执行" << endl;
}
};
int main()
{
int myi = 6;
Lei lei = Lei(myi);
//将类作为参数 创建一个线程
thread mthread(lei);
mthread.join();
cout << "我是主线程1!\n";
return 0;
}
执行结果
分析一下执行过程,
1.首先,在main函数中定义了一个类,类的构造函数被执行
2.将类作为参数创建一个线程,这个期间线程复制了这个类对象,所以类的拷贝构造函数被执行
3.主线程被阻塞,子线程执行类中的operator函数
4.子线程执行完毕,子线程中复制的类对象进行析构
5.主线程继续执行,return0 main函数中的类对象被析构
这其中有一个问题就是类接受的参数是一个int类型的引用,而不是值(值参数传递和引用参数传递的区别),因而只能使用join()让主线程等待子线程执行。若使用detach(),当主线程执行完成之后,就收回了int参数的内存空间,而子线程可能还没有执行完成,还会调用这个int引用,就会出现引用参数内存空间被注销的错误。
所以要避免上述情况的发生,要不使用值作为参数,要不使用join让主线程等待子线程。
通过lambda函数创建一个线程
#include <iostream>
#include <thread>
using namespace std;
int main()
{
//定义一个lambda函数
auto mylambda = [] {
cout << "lambda函数执行" << endl;
};
thread mthread(mylambda);
mthread.join();
cout << "我是主线程1!\n";
return 0;
}
结果如下