45 C++11 线程启动,结束,创建线程方法,join(),detach(),joinable()方法

 一 范例演示线程的创建

1.thread 类

前面的内容知道,程序运行起来,生成一个进程,该进程所属的主线程从main方法开始自动运行直到return 结束。

我们创建一个线程,也要从一个函数开始运行,一旦这个函数运行起来,就代表着我们这个线程开始运行,一旦这个函数运行结束,就代表着这个线程运行结束。

C++11提供了thread 这个类,因此第一步就是要 #include

使用 thread 类 ,构建对象的时候,传递的参数是一个方法,我们这里 是:mythreadmethod().

暂时没有传递参数。

我们知道,当主线程执行完毕后,进程也就挂了。如果主线程都执行完毕了,子线程还没有执行完毕,那么一般情况下,进程就会有runtime exception。

因此,在一般情况下,我们要让主线程等待子进程结束。因而引出了join()方法的使用

// 002createthread_join_detach.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

#include 
#include 
using namespace std;

void mythreadmethod() {
	cout << "mythreadmethod start..." << endl;

	cout << "mythreadmethod end..." << endl;
}
int main()
{
    std::cout << "Hello World start!\n";

	thread mythread(mythreadmethod);//这句话的意思是:1.创建一个子线程;2.该线程执行起点是mythreadmethod方法;3.mythreadmethod方法就已经抢占CPU开始执行,但是并不一定能抢过其他线程。
	mythread.join();//join方法的意思是:作用是阻塞主线程,让主线程等待子线程执行完毕,然后子线程和主线程汇合,然后再沿着主线程没有完成代码往下走。

	std::cout << "Hello World end!\n";
}

2.join()

作用是阻塞主线程,让主线程等待子线程执行完毕,然后子线程和主线程汇合,然后再沿着主线程没有完成代码往下走。

2.1 主线程阻塞等待,直到子线程执行完毕

2.2 子线程只能就算执行完毕了呢?就是创建子线程时,传递的方法 执行 完成了

2.3 不加 join()方法会怎么样呢?不会编辑错误,但是运行时候,会有几率 runtime exception。

        原因也很简单,当主线程先于子线程执行完成的case发生的时候:

                主线程结束 = 进程结束

                但是这时候子线程没有结束,那么这时候子线程依附于谁存在呢?换句话说:子线程中的临时变量,方法等,谁来回收呢?因此就有runtime exception

3.detach() 老师不建议使用,坑太多,除非有必要,

从上面知道,传统多线程程序:主线程使用join()方法等到子线程执行完毕,然后再执行自己的逻辑。

那么能不能主线程自己结束就结束,不用管子线程呢?

detach()方法就是干这个的。

使用detach()的意思是:

3.1主线程不和子线程汇合了

3.2子线程原本关联的主线程,现在就不在和主线程关联了,这个子线程就会驻留在后台运行。

3.3该子线程会被C++运行时库接管,当子线程执行完毕后,由运行时库(实际上是守护线程,这个要知道linux的一些相关进程线程的知识才懂,如果不懂,就大致理解为有人接管就可以了)清理该线程相关资源

3.4 detach 的坑 - 后续章节上专门研究

当主线程结束的时候,主线程中的值能否使用?

如果线程对象传递的方法中有参数,且这个参数是从主线程传递过去的,当主线程运行结束后,那么这个参数能否使用?

4.joinable()

该函数的作用是判断,join()或者 detach()方法能否使用?

运用时机:当程序很大的,最好判断一下。

结论:

当使用了join方法后,就不能再次使用join 和 detach方法了

当使用了detach方法后,就不能再次使用join 和 detach方法了

5. 如果join 和 detach都不写,会怎么样呢?

会runtime exception,原因未知。

二 用类创建线程以及注意问题

1.使用类对象,这个类对象需要实现operator()()方法,即()的重载。

class AA {
public:
	void operator()() {
		cout << "class AA operator()() start..." << endl;
		cout << "class AA operator()() end..." << endl;
	}
	int age;
};


//运行结果为:
//Hello World0 start!
//class AA operator()() start...Hello World1 end!
//	Hello World2 end!
//	Hello World3 end!
//	Hello World4 end!
//
//	class AA operator()() end...
//	Hello World5 end!
//	Hello World6 end!
void main() {
	AA aa;
	std::cout << "Hello World0 start!\n";
	thread mythread(aa);
	std::cout << "Hello World1 end!\n";
	std::cout << "Hello World2 end!\n";
	std::cout << "Hello World3 end!\n";
	std::cout << "Hello World4 end!\n";

	mythread.join();

	std::cout << "Hello World5 end!\n";
	std::cout << "Hello World6 end!\n";

}

//创建线程的方法,使用operator()函数做为 线程的入口函数
class Teacher141 {
public:
	void operator()() {
		for (int i = 0; i < 10;i++) {
			cout << "Teacher141 的 operator() 没有参数的方法被调用" << endl;
		}

	}
	void operator()(int num ) {
		for (int i = 0; i < 10;i++) {
			cout << "Teacher141 的 operator(int num) 的方法被调用: num = " << num << endl;
		}
	}

	void Teacher141func(int num) {
		m_age = num;
		cout << "Teacher141 的 operator() 没有参数的方法被调用" << endl;
	}

	int m_age;

};

//operator()()做thread 启动方法入口
void main() {

	cout << " test thread start " << endl;
	//operator()()做thread 启动参数
	Teacher141 t1;
	thread mythread1(t1);


	//operator()(T t)做thread 启动参数
	Teacher141 t2;
	thread mythread12(t2,20);

	mythread1.join();
	mythread12.join();

	//test thread start
	//	Teacher141 的 operator() 没有参数的方法被调用
	//	Teacher141 的 operator() 没有参数的方法被调用
	//	Teacher141 的 operator() 没有参数的方法被调用
	//	Teacher141 的 operator() 没有参数的方法被调用
	//	Teacher141 的 operator() 没有参数的方法被调用
	//	Teacher141 的 operator() 没有参数的方法被调用Teacher141 的 operator(int num) 的方法被调用: num = 20
	//	Teacher141 的 operator(int num) 的方法被调用 : num = 20
	//	Teacher141 的 operator(int num) 的方法被调用 : num = 20
	//	Teacher141 的 operator(int num) 的方法被调用 : num = 20
	//	Teacher141 的 operator(int num) 的方法被调用 : num = 20
	//	Teacher141 的 operator(int num) 的方法被调用 : num = 20
	//	Teacher141 的 operator(int num) 的方法被调用 : num = 20
	//	Teacher141 的 operator(int num) 的方法被调用 : num = 20
	//	Teacher141 的 operator(int num) 的方法被调用 : num = 20
	//	Teacher141 的 operator(int num) 的方法被调用 : num = 20

	//	Teacher141 的 operator() 没有参数的方法被调用
	//	Teacher141 的 operator() 没有参数的方法被调用
	//	Teacher141 的 operator() 没有参数的方法被调用
	//	Teacher141 的 operator() 没有参数的方法被调用
	//	test thread end


	cout << " test thread end " << endl;

}

2.使用类的成员函数来作为 线程的入口函数。

//类的成员函数做 线程启动函数入口
class Teacher142 {
public:
	void writeTeacherName() {
		for (int i = 0; i < 1000; i++) {
			cout << " 子线程id 为 : " << this_thread::get_id() << "   i = " << i << endl;
		}
	}
};

void main() {
	Teacher142 tea;
	int a = 10;
	thread mythread(&Teacher142::writeTeacherName,&tea);

	for (int i = 0; i < 1000;i++) {
		cout << "主线程id 为 : " << this_thread::get_id() << "   i = " << i << endl;
	}
	mythread.join();
}

三用lambda表达式

[](){}

//运行结果为:
//Hello World0 start!
//mylambdathread start...Hello World1 end!
//Hello World2 end!
//Hello World3 end!
//Hello World4 end!
//
//mylambdathread end...
//Hello World5 end!
//Hello World6 end!
void main() {
	std::cout << "Hello World0 start!\n";
	auto mylambdathread = []() {
		cout << "mylambdathread start..." << endl;
		cout << "mylambdathread end..." << endl;
	};
	thread mythread(mylambdathread);
	std::cout << "Hello World1 end!\n";
	std::cout << "Hello World2 end!\n";
	std::cout << "Hello World3 end!\n";
	std::cout << "Hello World4 end!\n";
	mythread.join();
	std::cout << "Hello World5 end!\n";
	std::cout << "Hello World6 end!\n";
}

你可能感兴趣的:(c++)