#include<iostream>
#include<thread>
using namespace std;
//自己创建的线程也要从一个函数(初始函数)开始运行
void myPrint()
{
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 << "\n******我的线程执行完毕了*******" << endl;
}
class Test
{
public:
int &m_i; //引用
Test(int &i):m_i(i){
cout << "执行Test构造函数" << endl;
}
Test(const Test & ta) :m_i(ta.m_i)
{
cout << "执行Test拷贝函数" << endl;
}
~Test()
{
cout << "执行Test析构函数" << endl;
}
void operator()() //重载()的函数,(没有参数)
{
/*cout << "我的线程operator()开始执行了1" << endl;
cout << "我的线程operator()开始执行了2" << endl;
cout << "我的线程operator()开始执行了3" << endl;
cout << "我的线程operator()开始执行了4" << endl;
cout << "我的线程operator()开始执行了5" << endl;
cout << "我的线程operator()开始执行了6" << endl;*/
cout << "1:m_i"<< "的值为" << m_i << endl; //当主线程结束,主线程对应资源被回收,此时可能会打印出不可预料的结果
cout << "2:m_i" << "的值为" << m_i << endl;
cout << "3:m_i" << "的值为" << m_i << endl;
cout << "4:m_i" << "的值为" << m_i << endl;
cout << "5:m_i" << "的值为" << m_i << endl;
cout << "6:m_i" << "的值为" << m_i << endl;
//...
cout << "\n******我的线程operator()执行完毕了*******" << endl;
}
};
int main()
{
//程序运行起来,生成一个进程,进程所属的主线程开始自动运行
cout << "主线程启动" << endl; //实际上是主线程在执行,主线程从main()函数返回,则整个进程执行完毕
//主线程从main函数开始执行,自己创建的线程,也需要从一个函数开始执行(初始函数),一旦这个函数运行完毕,就代表这个线程运行结束。
//整个进程是否执行完毕的标志是主线程是否执行完毕,若主线程完毕,子线程未执行完,一般情况下子线程会被操作系统强行终止
//所以,想保持子线程的运行状态,通常情况下要让主线程一直保持运行(稳定)(例外:detach(),分离)
//如果主线程执行完毕了,但子线程没执行完毕,则这种程序员是不合格的,写出来的程序也是不稳定的
//detach:分离,主线程不和子线程汇合了,你主线程执行你的,我子线程执行我的,你主线程也不必等我子线程运行结束,不影响子线程的执行
//引入detach的原因:有多个子线程时,主线程可以不必逐个等待众多子线程的结束
//一旦detach后,与主线程关联的thread对象就会失去与主线程的关联,此时这个子线程会驻留在后台运行(主线程失去对子线程的控制)
//子线程与主线程失去联系后,被C++运行时库接管,子线程运行结束时由运行时库负责清理该线程的相关资源(守护线程)
//joinable():判断是否可以成功使用join()或者detach();返回true或者false (join或detach后,都不能再进行join或detach)
//方法一:函数
//thread:是个标准库里的类
thread mytobj(myPrint);//1.创建了线程,线程执行起点(入口)为函数myPrint; 2.myPrint线程开始执行
/*if (mytobj.joinable())
{
cout << "Before:mytobj.joinable()==true" << endl;
}
else
{
cout << "Before:mytobj.joinable()==false" << endl;
}*/
mytobj.join();//join():加入/汇合。“阻塞”主线程,让主线程等待子线程执行完毕,然后子线程和主线程汇合,然后主线程再往下走
//主线程阻塞到这里等待myPrint执行完毕,当子线程执行完毕,这个join就执行完毕,主线程就继续往下走
//mytobj.detach(); //对它调用detach后不能再对它join了
//有两个线程,相当于整个程序的执行有两条线同时在走,所以,可以同时干两个事情。即使一条线被堵住了,另外一条线不被影响,继续运行。
/*if (mytobj.joinable())
{
cout << "After:mytobj.joinable()==true" << endl;
}
else
{
cout << "After:mytobj.joinable()==false" << endl;
}*/
//二:其他创建线程的方法
//(2.1)用类对象(可调用对象)
//int i = 6;
//Test test(i);
//thread mytobj2(test);//test:可调用对象
mytobj2.join();//等待子线程执行结束,会出现两个析构函数:先是线程中复制的对象被析构,再是主线程的对象的析构
//mytobj2.detach();//在调用后,主线程执行结束时,test这个对象不在了(被回收了),但不影响线程的使用,因为这个test对象实际上是被 复制 到线程中去的
// //执行完后,主线程的test对象被销毁,但是复制到线程的对象依旧存在。所以只要这个类对象没有引用,指针等,那么就不会产生问题
//三:用lambda表达式
//auto mylamthread = [] {
// cout << "我的lambda线程开始执行了1" << endl;
// cout << "我的lambda线程开始执行了2" << endl;
// cout << "我的lambda线程开始执行了3" << endl;
// cout << "我的lambda线程开始执行了4" << endl;
// cout << "我的lambda线程开始执行了5" << endl;
// //...
// cout << "*****我的lambda线程执行结束了*****" << endl;
//};
//thread mytobj3(mylamthread);
//mytobj3.join();
mytobj3.detach();
cout << "主线程执行1" << endl;
cout << "主线程执行2" << endl;
cout << "主线程执行3" << endl;
cout << "主线程执行4" << endl;
cout << "主线程执行5" << endl;
cout << "\n*****主线程收尾,正常安全退出******" << endl;
//system("pause");
return 0;
}