线程的三种创建、join和detach、线程创建与结束

#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;
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值