C++ 教程 - 09 多线程处理

thread标准库

  • C++ 11 后添加了新的标准线程库 std::thread 类,
  • 需引入头文件<thread>
  • 支持windows,linux平台(linux平台下需要导入<pthread.h>,编译时并链入libpthread.so),可以利用多核cpu,并行执行,但是python的多线程却不可以利用多核心;
  • 声明变量并创建线程对象,如 thread th1; 调用无参构造,生成一个空的线程对象;
  • thread th(callable, args),传入调用函数及参数;
    • callable,可为函数;
    • callable,可为可调用对象;
    • callable,可为lambda 表达式(无名函数)
    • th.join() 等待当前子线程执行结束;
  • std::this_thread::sleep_for(chrono::seconds(1)) 线程内部延迟1s;
  • std::this_thread::get_id();
  • std::thread::harware_concurrency() 获取cpu核心数, 一般num + 1 个线程;
  • g++编译时,指定 -std=c++11 或者更新的版本;
#include <iostream>
#include <string>

// C++11后引入的 线程 标准库 std::thread 类  std::this_thread
#include <thread>
#include <chrono> // 延迟时间
using namespace std;



// 定义类
class People {
public:
	int age; // 实例 成员变量
	string name;

	People() {
		cout << "走无参构造函数..." << endl;
		this->age = 30;
	}
	People(const string& name, const int& age) {
		cout << "走有参构造函数..." << endl;
		this->name = name;
		this->age = age;
	}

	virtual ~People() {
		cout << "删除对象" << endl;
	}

	// 重载 函数调用()运算符,对象才可以调用
	void operator()(int age) {
		for (int i = 0; i < age; i++) {
			cout << "param age:" + to_string(age) << endl; // to_string 将int转为字符串,字符串支持 + 连接
			cout << "成员age:" << this->age << endl;

			// 延迟1s
			this_thread::sleep_for(chrono::seconds(1));
			cout << this_thread::get_id() << endl;
		}
		
	}
	
};


struct book { // 定义结构体,同C语法一致,只不过C++中可以单独使用book类声明变量,而C中必须使用struct book 声明
	char *title;
	double price;
};


// 函数
void myFunc(book arr[], int arrLen) {
	for (int i = 0; i < arrLen; i++) {
		cout << "当前书籍:" << endl;
		cout << arr[i].title << endl;
		cout << arr[i].price << endl;

		//std::this_thread 线程延迟1s
		this_thread::sleep_for(chrono::seconds(1));
		// 打印线程id
		cout << "线程id:" << this_thread::get_id() << endl; 
		cout << "" << endl;
	}
}


int main() {
	
	// 创建空子线程
	thread th1;
	
	// 创建子线程,并传参 '调用函数'、参数
	struct book arr[3]; // 数组分配内存,并创建结构体对象
	
	// 对象的指针属性,必须动态分配内存
	arr[0].title = new char(20);
	arr[0].title = (char*)"三国演义"; // 为对象赋值
	arr[0].price = 23.5;

	arr[1].title = new char(20);
	arr[1].title = (char*)"西游记";
	arr[1].price = 30.5;

	arr[2].title = new char(20);
	arr[2].title = (char*)"水浒传";
	arr[2].price = 28.5;

	thread th2(myFunc, arr, 3);

	// 创建子线程,并传参 lambda 表达式 (无名函数)
	auto exp1 = [](const int& num) { cout <<"lambda:" <<  num << endl; }; //  必须有 ; 号
	thread th3(exp1, 5);


	// 创建子线程,并传入 ‘可调用对象’、参数
	thread th4(People(), 20);


	// 等待子线程结束
	// th1.join(); // 空的子线程  不能.join()
	th2.join();
	th3.join();
	th4.join();

	return 0;
}

 

守护线性

  • 以上多线程的案例中,th.join() 等待子线程执行结束,会阻塞主线程;
  • th.detach() 设置为守护线程,后台运行,不影响主线程,但随着主线程的退出而退出;
  • 以下为linux案例;
#include <iostream>
#include <thread>
#include <chrono>
#include <pthread.h>
using namespace std;

void func(const int& a, const int& b){
    for(int i=0;i<100;i++){
    this_thread::sleep_for(chrono::seconds(1));
    cout << "sub thread running..." << endl;
    }

}

int main(){

  int a, b;
  a = 1;
  b = 2;
  thread th1(func, a, b);
  th1.detach(); // daemon thread

  cout << "main thread running..." << endl;
  // main thread
  this_thread::sleep_for(chrono::seconds(10));
  return 0;

}

 

pthread库

  • linux下使用pthread库创建子线程;
  • 需包含头文件<pthread.h>,且编译时链入libpthread.so动态库;
    • pthread_t 线程id类型;
    • pthread_create(&curThID, attr, funcName, void* args) 创建线程并执行,成功返回0,并将线程id存入curThID变量地址; attr线程对象的属性(可NULL); funcName为返回void* 且参数为void*的函数
    • 默认为守护线程,主线程结束时,不管子线程有没有结束,均都随主线程一起退出;
    • pthread_exit(NULL) ,在主线程中等待子线程执行结束;
    • pthread_attr_t 线程对象属性类型;
    • pthread_attr_init(&attr) 线程对象属性初始化;
    • pthread_attr_delete(attr) 线程对象属性删除;
    • pthread_join(thId, status) 连接线程,顺序执行;
    • pthread_detach() 分离线程;

 

在这里插入代码片
  • 13
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

laufing

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值