- 自己用代码创建的其他线程
- 需要从一个
函数
开始运行- 当这个
函数
运行完毕的时候- 代表这个线程
运行结束
什么是多线程
不是一条线执行,而是多条线,可以同时干多个事,即使一条线被堵住了,另一条也可以顺利执行
主线程应该做的是等待子线程执行完毕后
,自己才能最终退出
如果想让子线程不被OS强行终止
需要让
主线程
一直保持运行,不要让主线程
运行完毕即可
thread类和join()函数
- thread类是用来构建
子线程对象
的 - join()函数是用来
阻塞主线程
,让主线程等待子线程执行完毕
的函数
主线程阻塞到
join()
这里等待go()
执行完,当子线程执行完毕(然后子线程和主线程汇合),这个join()就会执行完毕,主线程就可以继续向下执行。
如果没有join()函数
就会发生异常
如果有join()函数
就可以顺利执行
detach()的使用
detach()是可以让主线程和子线程分离
- 当调用了detach()之后,与主线程关联的thread对象就会失去与这个主线程的关联
- 此时这个子线程会驻留在
后台
运行(主线程和这个子线程失去联系)
如果主线程提前退出了,子线程就会被C++运行时库接管,当子线程执行完的时候,运行时库会清理这个子线程的相关资源
这个线程一般被称为
守护进程
detach()使用结果
detach()导致输出的格式是乱的,随机的,detach()后线程是不受控制的
什么是joinable()
如果一直没有调用过join()和detach(),那么joinable()就是true
如果调用过,那么joinable()就是false
因为join()和detach()不能同时调用,并且只能调用一次
其他创建线程的手法
之前的创建手法回顾
thread myobj(go)
这个go()是一个函数,也是一个可调用对象
类
(或者说是类对象
)也可以作为一个可调用对象
如果使用detach()
可以看到析构函数只调用了一个,这个析构函数是析构主线程的那个可调用对象的
,因为子线程那个还没执行完(蓝色箭头
)
如果使用join()
第一个析构函数是子线程的
第二个析构函数是主线程的
“复制”还是“引用 or 指针”
如果我们用的是join(),那么用引用
还是值传递
都可以
如果用的是detach(),当主线程退出的时候,myi
变量会被系统自动销毁,那么这个时候子线程中就没有东西可以执行了,就会有异常
。
需要注意的是这里的可调用对象
ta
进入子线程后是直接复制
了一份,所以拷贝构造函数
被执行了。
- 所以说还是用join稳啊。
lambda表达式
使用join()
使用detach()
小结
可以用函数、类对象、lambda表达式创建线程
,作为线程的入口
博客示例代码
- thread和join()
#include <iostream>
#include <thread>
using namespace std;
void go()
{
cout << "子线程开始执行了!" << endl;
cout << "子线程运行完毕了!" << endl;
}
int main()
{
thread myObj(go);
myObj.join();
cout << "主线程开始执行了!" << endl;
return 0;
}
- detach()
#include <iostream>
#include <thread>
using namespace std;
void go()
{
cout << "子线程开始执行了!" << endl;
cout << "子线程运行完毕了1" << endl;
cout << "子线程运行完毕了2" << endl;
cout << "子线程运行完毕了3" << endl;
cout << "子线程运行完毕了4" << endl;
cout << "子线程运行完毕了5" << endl;
cout << "子线程运行完毕了6" << endl;
cout << "子线程运行完毕了7" << endl;
cout << "子线程运行完毕了8" << endl;
cout << "子线程运行完毕了9" << endl;
cout << "子线程运行完毕了10" << endl;
}
int main()
{
thread myObj(go);
// myObj.join();
myObj.detach();
cout << "fucking bitch 1" << endl;
cout << "fucking bitch 2" << endl;
cout << "fucking bitch 3" << endl;
cout << "fucking bitch 4" << endl;
cout << "fucking bitch 5" << endl;
cout << "fucking bitch 6" << endl;
cout << "fucking bitch 7" << endl;
cout << "fucking bitch 8" << endl;
cout << "fucking bitch 9" << endl;
cout << "fucking bitch 10" << endl;
return 0;
}
- 类对象
#include <iostream>
#include <thread>
using namespace std;
class TA
{
public:
int m_i;
TA(int i) : m_i(i) { cout << "TA()构造函数被执行" << endl; }
TA(const TA& ta) : m_i(ta.m_i) { cout << "TA()拷贝构造函数被执行" << endl; }
~TA() { cout << "~TA()析构函数被执行" << endl; }
void operator() ()
{
cout << "m_i1的值为:" << m_i << endl;
cout << "m_i2的值为:" << m_i << endl;
cout << "m_i3的值为:" << m_i << endl;
cout << "m_i4的值为:" << m_i << endl;
cout << "m_i5的值为:" << m_i << endl;
cout << "m_i6的值为:" << m_i << endl;
cout << "m_i7的值为:" << m_i << endl;
cout << "m_i8的值为:" << m_i << endl;
}
};
int main()
{
int myi = 6;
TA ta(myi);
thread myObj(ta);
myObj.join();
//myObj.detach();
cout << "fucking bitch 1" << endl;
cout << "fucking bitch 2" << endl;
cout << "fucking bitch 3" << endl;
cout << "fucking bitch 4" << endl;
cout << "fucking bitch 5" << endl;
cout << "fucking bitch 6" << endl;
cout << "fucking bitch 7" << endl;
cout << "fucking bitch 8" << endl;
cout << "fucking bitch 9" << endl;
cout << "fucking bitch 10" << endl;
return 0;
}
- lambda表达式
#include <iostream>
#include <thread>
using namespace std;
int main()
{
auto mylambdathread = []
{
cout << "我的线程开始执行了" << endl;
cout << "我的线程执行结束了" << endl;
cout << "我的线程执行结束了" << endl;
cout << "我的线程执行结束了" << endl;
cout << "我的线程执行结束了" << endl;
};
thread myobj(mylambdathread);
// myobj.join();
myobj.detach();
cout << "Fucking bitch" << endl;
return 0;
}