线程的创建
进程的生命周期是和主线程相同的。进程的开启伴随着主线程的出现,主线程执行完毕代表着进程的结束。在编译器上,主线程是从main函数开始,当主线程从main函数上返回,就代表着进程的结束。一般情况下,如果主线程执行结束,也就是进程结束时还有其他线程未执行完毕,也会被强制终止。所以,对于自主创建的线程要确保其在主线程结束执行前执行完毕或者保持主线程,否则就可能达不到预期的效果。
#include<iostream>
#include<thread>
using namespace std;
void nowork()//线程入口
{cout<<"nowork线程"<<endl;
}int main()
{thread newdozer(nowork);if(newdozer.joinable())//判断线程是否可以join或detach{newdozer.join();//使用join阻塞主线程直到新线程执行完毕}else{cout<<"失败"<<endl;}
}
创建线程需要使用include<thread>将头文件包含进来。与main函数相似,自定义的函数也可以作为新创建线程的通路。然后创建thread对象,并使用自定义的函数作为进程入口进行初始化。这样一条新线程就创建出来了。当代码执行此段后,就会自动通过线程入口启动新线程。为了保证新线程执行情况,还要使用thread成员中的join或者detach确保新线程执行的完全。join的作用是阻塞主线程的执行直到新线程执行完毕,就是让主线程等一等新线程。detach的作用是将线程从进程中分离出,转而在后台运行,这样即使主线程运行完毕,新线程也不会停止运行。但是一个线程被detach处理后就无法再与其进行同步或其他形式的交互了,会失去对该线程的控制。joinable可以用来判断是否可以进行join或者detach操作,可以返回true,不行返回false。
其他创建线程的方法
使用类对象创建线程
#include<iostream>
#include<thread>
using namespace std;
class A
{
public:int &m_i;
public:A(int &a):m_i(a) {}operator()(){cout<<m_i<<endl;cout<<"新线程"<<endl;}
};int main()
{A ta;thread newdozer(ta);newdozer.join();
}
使用类创建新线程,需要先创建类对象,再用类对象初始化thread对象。这样新线程会复制一个类对象作为新线程的入口。如果类对象的成员中包含主线程中的变量的引用、指针等,就不要使用detach确保线程的执行。因为如果主线程先被执行完毕销毁的话,那么新线程使用这些成员就访问了已被释放的内存,从而偏离设想。
使用lambda表达式
#include<iosteam>
#include<thread>
using namespace std;
int main()
{auto lambthread [](){cout<<"新线程"<<endl;}thread newdozer(lambthread);newdozer.join();
}
使用类成员函数
#include<iosream>
#include<thread>
using namespace std;
class A
{
public:void nowork(int a){cout<<"新线程"<<endl;}
};
int main()
{A obj;thread newdozer(&A::nowork,obj,666);newdozer.join();
}