- 整个进程执行的完毕结束的标志是主线程结束;
- 此时,如果其他子线程还没有执行完毕,那么子线程也会被操作系统强行终止,系统抛出异常
- 良好的程序应该是主线程等待子线程执行完毕后,自己才能退出
- 步骤:a)包含头文件
b)自定义线程执行函数
c)创建子线程thread mythread(mySonThread)
d)join() :汇合,阻塞主线程并等待子线程执行完,继续往下执行主线程 - detach():分离,主线程不与子线程汇合,各自独立自行,主线程结束,子线程也能够运行
一旦detach()后,与这个线程关联的thread对象就会失去与这个主线程的关联,此时子线程就会驻留后台运行
这个子线程将会被系统运行时库接管,当这个子线程执行完成后,由运行时库负责清理该线程相关的资源(守护线程)
使用detach将会失去对线程的控制 - join与detech不能同时使用
- joinable():判断线程是否join或者detach成功,返回true成功,false失败
- 如果线程传递int 这种简单的数类型,建议值传递,不要传引用
- 如果传递类对象,避免隐士转换,要在创建线程这一步中,构建临时对象。在线程执行函数中,参数入口采用引用的形式,避免又多一次构造
#include <iostream>
#include <unistd.h>
#include <thread>
#include "stdio.h"
#include <string>
using namespace std;
int mySonThread()
{
cout <<"子线程:开始"<<endl;
for(int i=0;i<10;i++) {
cout <<"子线程执行第:"<<i<<" 次"<<endl;
}
cout <<"子线程结束"<<endl;
return 0;
}
class SonTheardClass{
public:
SonTheardClass(int i):num(i)
{
cout <<"构造函数被执行,线程ID:"<<this_thread::get_id()<<endl;
}
SonTheardClass(const SonTheardClass &mysonthread):num(mysonthread.num)
{
cout<<"拷贝构造被执行,线程ID:"<<this_thread::get_id()<<endl;
}
void operator() ()
{
cout<<"mySonTheardClass is begining!"<<endl;
cout<<"作为类参数对象被执行,线程ID:"<<this_thread::get_id()<<endl;
cout<<"mySonTheardClass is over!"<<endl;
}
~SonTheardClass(){
cout<<"析构被执行,线程ID"<<this_thread::get_id()<<endl;
}
public:
int num;
};
void mytempthread(const int &i,char *buff1,const string &buff2)
{
cout<<"mytempthread is begining!"<<endl;
cout<<"i= "<<i<<endl;
const int *addr_i_thread=&i;
cout<<"addr_i_thread= "<<addr_i_thread<<endl;
printf("addr_buff1_thread= %lx\n",buff1);
printf("addr_buff2_thread= %lx\n",&buff2);
cout<<"mytempthread is over!"<<endl;
}
int main(int argc, char *argv[])
{
cout << "主线程:开始"<<endl;
SonTheardClass mySonTheardClass(6);
thread thread1(mySonThread);
thread1.join();
thread thread2(mySonTheardClass);
thread2.join();
int i=2;
const int *addr_i=&i;
cout<<"addr_i= "<<addr_i<<endl;
char buff[]="temp buff";
cout<<"addr_buff= "<<&buff<<endl;
thread thread3(mytempthread,i,buff,string(buff));
thread3.join();
cout<<"主线程:结束"<<endl;
return 0;
}