主线程从 main() 函数开始执行,子线程也需要从一个函数开始运行(初始函数),一旦此函数运行完毕,该线程就结束了。

1 进程结束的标志

主线程执行完毕(子线程不论是否结束都会被终止,有例外情况)

2 创建线程

#include <iostream>
#include <thread>

using namespace std;

void SubThreadPrint() {
    cout << "子线程开始运行" << endl;
    cout << "子线程运行完毕" << endl;
    return;
}

int main() {
    // 创建线程
    // 执行线程
    thread my_thread(SubThreadPrint);

    // 阻塞主线程
    // 子线程执行完,主线程继续往下执行
    my_thread.join();

    // 主线程不再等待子线程
    // 子线程与主线程失去关联,驻留在后台,由C++运行时库接管
    // my_thread.detach();

    // 判断是否可以成功使用 join() 或者 detach()
    //如果返回 true,证明可以调用 join() 或者 detach()
    //如果返回 false,证明调用过 join() 或者 detach(),join() 和 detach() 都不能再调用了
    if (my_thread.joinable()) {
        cout << "可以调用可以调用join()或者detach()" << endl;
    } else {
        cout << "不能调用可以调用join()或者detach()" << endl;
    }

    cout << "Hello World!" << endl;
    return 0;
}

3 其他创建线程的方法

理论依据:

线程类参数是一个可调用对象。

一组可执行的语句称为可调用对象,C++中的可调用对象可以是函数、函数指针、lambda表达式、bind创建的对象或者重载了函数调用运算符的类对象。

3.1 创建类,重载函数调用运算符,初始化该类的对象,把该对象作为线程入口地址

#include <iostream>
#include <thread>

using namespace std;

class SubThreadClass {
public:
	// 不能带参数
	void operator()() {
		cout << "子线程开始运行" << endl;
		cout << "子线程运行完毕" << endl;
	}
};

int main() {
	SubThreadClass sub_thread_class;

	// 创建线程
	// 执行线程
	thread my_thread(sub_thread_class);

	// 阻塞主线程
	// 子线程执行完,主线程继续往下执行
	my_thread.join();

	// 主线程不再等待子线程
	// 子线程与主线程失去关联,驻留在后台,由C++运行时库接管
	// my_thread.detach();

	// 判断是否可以成功使用 join() 或者 detach()
	//如果返回 true,证明可以调用 join() 或者 detach()
	//如果返回 false,证明调用过 join() 或者 detach(),join() 和 detach() 都不能再调用了
	if (my_thread.joinable()) {
		cout << "可以调用可以调用join()或者detach()" << endl;
	}
	else {
		cout << "不能调用可以调用join()或者detach()" << endl;
	}

	cout << "Hello World!" << endl;
	return 0;
}

3.2 lambda 表达式创建线程

#include <iostream>
#include <thread>

using namespace std;

int main() {
	auto lambda_thread = [] {
		cout << "子线程开始执行了" << endl;
		cout << "子线程开始执行了" << endl;
	};

	// 创建线程
	// 执行线程
	thread my_thread(lambda_thread);

	// 阻塞主线程
	// 子线程执行完,主线程继续往下执行
	my_thread.join();

	// 主线程不再等待子线程
	// 子线程与主线程失去关联,驻留在后台,由C++运行时库接管
	// my_thread.detach();

	// 判断是否可以成功使用 join() 或者 detach()
	//如果返回 true,证明可以调用 join() 或者 detach()
	//如果返回 false,证明调用过 join() 或者 detach(),join() 和 detach() 都不能再调用了
	if (my_thread.joinable()) {
		cout << "可以调用可以调用join()或者detach()" << endl;
	}
	else {
		cout << "不能调用可以调用join()或者detach()" << endl;
	}

	cout << "Hello World!" << endl;
	return 0;
}

3.3 把某个类中的某个函数作为线程的入口地址

#include <iostream>
#include <thread>

using namespace std;

class Data_ {
public:
	void GetMsg() {
		cout << "GetMsg 子线程开始执行了" << endl;
		cout << "GetMsg 子线程开始执行了" << endl;
	}
	void SaveMsg() {
		cout << "SaveMsg 子线程开始执行了" << endl;
		cout << "SaveMsg 子线程开始执行了" << endl;
	}
};

int main() {
	Data_ data;

	// 第一个 & 是取址
	// 第二个 & 是引用
	thread my_thread1(&Data_::GetMsg, &data);
	thread my_thread2(&Data_::SaveMsg, &data);

	my_thread1.join();
	my_thread2.join();

	cout << "Hello World!" << endl;
	return 0;
}

运行结果如下

SaveMsg 子线程开始执行了
SaveMsg 子线程开始执行了
GetMsg 子线程开始执行了
GetMsg 子线程开始执行了
Hello World!

C:\Users\null\source\repos\Project1\Debug\Project1.exe (进程 14644)已退出,代码为 0。
要在调试停止时自动关闭控制台,请启用“工具”->“选项”->“调试”->“调试停止时自动关闭控制台”。
按任意键关闭此窗口. . .