//#include <iostream>
//#include <vector>
//#include <map>
//#include <string>
//#include <thread>
//
//using namespace std;
//
////自己创建的线程也要从一个函数开始运行
////void myprint()
////{
//// cout << "我的线程开始执行了" << endl;
////
//// //...
//// //..
//// cout << "我的线程结束了" << endl;
//// cout << "我的线程结束了1" << endl;
//// cout << "我的线程结束了2" << endl;
//// cout << "我的线程结束了3" << endl;
//// cout << "我的线程结束了4" << endl;
//// cout << "我的线程结束了5" << endl;
//// cout << "我的线程结束了6" << endl;
//// cout << "我的线程结束了7" << endl;
//// cout << "我的线程结束了1" << endl;
//// cout << "我的线程结束了2" << endl;
//// cout << "我的线程结束了3" << endl;
//// cout << "我的线程结束了4" << endl;
//// cout << "我的线程结束了5" << endl;
//// cout << "我的线程结束了6" << endl;
//// cout << "我的线程结束了7" << endl;
////}
////class TA
////{
////public:
//// int &m_i;//这里定义一个引用变量
//// //TA(int &i):m_i(i){}//这里对引用变量赋值,m_i就是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()()//这里是仿函数,模仿函数的类,使用方式如同函数,本质是类中重载括弧运算符operator();
//// {
//// //cout << "我的线程开始执行了" << endl;
////
//// //cout << "我的线程结束了" << endl;
//// cout << "m_i1的值为:" << m_i << endl;//这里用了引用(所以别用),再detach状态下,主线程执行完了,这里
//// cout << "m_i2的值为:" << m_i << endl;//的m_i还在引用myi,而myi已经被释放,所以可能产生不可预料的结果
//// cout << "m_i3的值为:" << m_i << endl;
//// cout << "m_i4的值为:" << m_i << endl;
//// cout << "m_i5的值为:" << m_i << endl;
////
//// }
////};
//int main()
//{
// //范例演示线程运行的开始和结束
// //程序运行起来,生成一个进程,该进程所属的主线程开始自动运行;
// //cout<<"I love china"<<endl;//实际上这是主线程在执行,主线程从main()函数返回,则整个程序执行完毕
// //主线程从main()函数开始执行,那么我们自己创建的线程,也需要从一个函数开始执行(初始函数),一旦这个函数执行完毕,
// //就代表我们这个线程运行结束
//
// //整个进程是否执行完毕的标志事 主线程是否执行完毕,如果主线程执行完毕了,就代表整个线程执行完毕了。
// //此时,一般情况下,如果其他子线程没有执行完毕,那么那些子线程也会被操作系统强行终止。
// //所以,一般情况下,我们得到一个结论:如果大家保持子线程的运行状态,那么要让主线程一直保持运行
//
// //a)包含一个头文件thread
// //b)初始函数要写。
// //c)main中开始写代码
// //大家必须明确一点:有两个线程在跑,相当于整个程序有两条线在同时走,所以,可以同时干两件事。
// //即使一条线被堵住了,另一条线还是可以通信
// //(1.1)thread:是标准库里的类
// //(1.2)join():加入汇合,说白了就是阻塞,阻塞主线程,让主线程等待子线程执行完毕,然后子线程和主线程汇合,然后主线程再往下走
// //一个良好的程序,应该是主线程等待子线程执行完毕,自己才开始最终退出
// //(1.3)detecth():传统多线程程序主线程要等待子线程执行完毕,自己才最终退出
// //detecth:分离,也就是主线程不和子线程汇合了,各自执行,主线程不必等待子线程
// //为什么引入detecth:我们创建了很多子线程,让主线程逐个等待子线程结束,这个变成方法不太好,所以才引入
// //一旦detecth之后,与这个主线程关联的thread对象就会失去与这个主线程的关联,此时这个子线程就会驻留在后台运行(主线程与子线程失去联系)
// //这个子线程就相当于被c++运行时库接管,当这个子线程执行完毕后,由运行时库负责清理该线程相关的资源(守护线程)。
// //detach是线程myprint失去我们自己的控制。
// //(1.4)joinable():判断是否可以成功join()或者detach的;返回ture或false
//
//
// //myprint可调用对象。
// //thread mytobj(myprint);//创建了线程,线程执行起点(入口)myprint(),(2)myprint线程开始执行
// //if(mytobj.joinable())
// //{
// // cout << "2:jpinable()==true" << endl;
//
// //}
// //else
// //{
// // cout<< "2:jpinable()==false" << endl;
// //}
// //阻塞主线程并等待myprint子线程执行完
// //mytobj.join();//当子线程执行完毕,这个join()就执行完毕,主线程就继续往下走
//
//
// //mytobj.detach();//一旦调用了detach,就不能再用join,否则系统会报异常,有可能主线程执行完了子线程没执行完。
// //if (mytobj.joinable())
// //{
// // cout << "2:jpinable()==true" << endl;
// // //mytobj.join();
//
// //}
// //else
// //{
// // cout << "2:jpinable()==false" << endl;
// //}
// //cout << "I love china" << endl;
// //cout << "I love china1" << endl;
// //cout << "I love china2" << endl;
// //cout << "I love china3" << endl;
// //cout << "I love china4" << endl;
// //cout << "I love china5" << endl;
//
//
// //二:其他创建线程的手法
// //(2.1)用类,以及一个问题范例
// //疑问:一旦调用了detach(),那么主线程执行结束了,我这里用这个ta这个对象还在吗?
// //这个对象实际上时被复制到线程中去,执行完主线程后,ta被销毁,但是所复制的TA对象依旧存在,运行程序发现拷贝构造函数被执行,
// //运行程序出现了两次析构,一次是复制进去的TA对象的析构,一次是ta原对象的析构
// //所以只要你这个TA类对象没有引用,没有指针,那么就不会产生问题。
// //int myi = 6;
// //TA ta(myi);
// //thread mytobj3(ta);//ta:可调用对象。
// ////mytobj3.join();//等待子线程执行结束。
// //mytobj3.detach();
// //cout << "I love china" << endl;
//
// //(2.2)用lambda表达式
// auto mylamthread = []{
// cout << "我的线程开始执行了" << endl;
//
// cout << "我的线程结束了" << endl;
// };
// thread mytobj4(mylamthread);
// mytobj4.join();
//
// return 0;
//}
![]()