当前位置: 首页 > news >正文

24、如何在C++中创建和管理线程?【中高频】 -

  • 创建线程对象:
  //无参构造,该线程对象没有关联任何线程函数,也就是它没有启动任何线程:
  thread t1;
  //... 
  t1 = thread(func, 10);//移动构造(调用移动赋值函数)
  t1.join();
  
  //含参构造
  thread t1(func1, 1, 10);
  
  //thread 提供了移动构造函数,能够用一个右值线程对象来构造一个线程对象,以下两种都是 移动构造:
  thread t3 = thread(func, 4, 20);   // 创建匿名函数对象,赋值给 t3 (调用移动赋值函数)
  thread t4(std::move(thread(func, 10, 20))); // 显式move (调用移动构造函数)
  • 成员函数:

    join和detach都用于回收线程资源

    • join 函数

      • 功能是 连接一个已经终止的线程,并回收它的资源(调用一次,只能回收一个线程)。

      • 阻塞函数:调用它的线程会一直阻塞,直到 对应的线程终止 并被 join 函数回收,原线程才会继续执行

      • 任意一个线程都可以使用 join 来回收其他线程,但一般在主线程中使用

  #include <iostream>
  #include <thread>
  using namespace std;
  
  void func()
  {
     for(int i = -10; i > -20; i--)
      {
          cout << "from func():" << i << endl;
      }
  }
  
  int main()			//主线程
  {
  	thread t(func);	//子线程
  	t.join();		//等待子线程结束后才进入主线程
  	cout << "mian()" << endl;
      cout << "mian()" << endl;
      cout << "mian()" << endl;
  	return 0;
  }
  • detach函数

    • 功能是 分离一个线程,也就是当 调用detach的线程对象终止时,它的资源会自动 被系统回收,而不是被其他线程回收。

    • 非阻塞地回收线程

  #include <iostream>
  #include <thread>
  using namespace std;
  
  void func()
  {
     for(int i = -10; i > -20; i--)
      {
          cout << "from func():" << i << endl;
      }
  }
  
  int main()			//主线程
  {
  	cout << "mian()" << endl;
      cout << "mian()" << endl;
      cout << "mian()" << endl;
  	thread t(func);	//子线程
  	t.detach();		//分离子线程,让系统自动回收
  	return 0;
  }
  • joinable函数:

    • bool类型函数,它会表示当前的线程是否是可执行线程(能被join或者detach)
      • 1 -> 表示可以join或者detach
      • 0 -> 表示已经可以join或者detach,不可再重复回收了
    • 可以通过 joinable()函数 判断线程是否是有效的,如果是以下任意情况,则线程无效:
      • 线程对象没有关联函数
      • 线程对象的状态已经转移给其他线程对象
      • 线程已经调用join 或者detach结束

在这里插入图片描述

  • 创建线程对象后,如果向启动线程的话,必须要提供线程关联函数。线程函数一般情况下可按照以下四种方式提供:
    • 函数指针
    • lambda表达式
    • 函数对象
    • 包装器(function)
void ThreadFunc(int a) {
	cout << "Thread1" << a << endl;
}

void T()
{
	cout << "hello" << endl;
}

class TF
{
public:
	void TT()
	{
		cout << "NI" << endl;
	}
	void operator()()
	{
		cout << "Thread3" << endl;
	}
};

int main()
{
	// 线程函数为函数指针
	thread t1(ThreadFunc, 10);

	// 线程函数为lambda表达式
	thread t2([] {cout << "Thread2" << endl; });

	// 线程函数为函数对象
	TF tf;
	thread t3(tf);
	thread t5(&TF::TT, TF());

	//线程函数为包装器
	function<void()> t = T;
	thread t4(t);

	t1.join();
	t2.join();
	t3.join();
	t4.join();
	t5.join();
	cout << "Main thread!" << endl;
	return 0;
}
  • 禁止拷贝线程对象thread类 不允许拷贝构造以及赋值,但是可以移动构造和移动赋值,即一个线程对象关联的 线程的状态 转移给 其他线程对象,转移期间不影响线程的执行

  • 线程函数参数

    • 线程函数的参数是以 值拷贝 的方式 拷贝到线程栈空间中的,实际引用的是 线程栈中的拷贝,而不是外部实参。所以,即使参数是引用类型,最后也不能把改变后的结果带到外面
    • 注意:如果线程参数是类成员函数时,必须将this作为线程函数参数
http://www.dtcms.com/a/55221.html

相关文章:

  • 实现Django和Transformers 构建智能客服大模型(模拟订单系统)
  • olmOCR:高效精准的 PDF 文本提取工具
  • JavaScript中的引用类型与内存地址
  • Mysql回表查询、索引覆盖等概念
  • [java][JwtUtils ]生成token以及校验token相关方法
  • clickhouse安装路径
  • Easysearch 新功能: IK 字段级别词典
  • Windows网络编程之IOCP模型深度解析(万字长文)
  • 物联网中 对设备监测和设备控制
  • JavaScript基础-运算符的分类
  • Memory should not be managed manually(Code Smell)
  • macOS常用网络管理配置命令
  • 【第22节】C++设计模式(行为模式)-Iterator(迭代器)模式
  • 关于webpack的文件打包分割,并防止js文件缓存
  • 系统设计面试总结:4、单点登录SSO的概念、优势、OAuth2.0、具体实现(含时序图和跨域登录/登出的解决方案)
  • 如何在后端服务发布过程中使用蓝绿部署
  • AI资产管理系统与ERP对接API规范 v2.3
  • 小程序中下载文件 Vue3 写法
  • Linux(Centos 7.6)命令详解:vim
  • bert模型笔记
  • vim基本操作及常用命令
  • 【PLL】分频器:其他拓扑
  • Linux 进程管理
  • 大白话html语义化标签优势与应用场景
  • git如何解除远程仓库 改变远程仓库地址
  • Elasticsearch为索引设置自动时间戳,ES自动时间戳
  • 杂项知识笔记搜集
  • 【由技及道】量子跃迁部署术:docker+jenkins+Harbor+SSH的十一维交付矩阵【人工智障AI2077的开发日志011】
  • Java算法语法学习 美丽子集的数目 - 力扣 Map接口
  • 2025软件测试面试八股文(含答案+文档)