【C++11多线程】线程的创建与结束:thread

2023-10-27

1.普通函数作为线程函数

程序运行起来,生成一个进程,其中主线程从 main() 函数开始执行,当主线程从 main() 函数返回,则整个进程执行完毕。也就是说,整个进程是否执行完毕的标志是主线程是否执行完毕。

既然主线程从 main() 函数开始执行,那么我们自己创建的线程也需要从一个函数开始运行,一旦这个函数运行完毕,我们自己创建的线程也结束运行。

1.1 thread

头文件 #include <thread>

thread 是一个类,thread td(myThread) 是利用构造函数创建了一个 thread 类对象 td,传入参数 myThread 是一个可调用对象。

C++ 中的可调用对象可以是函数、函数指针、lambda表达式、bind创建的对象或者重载了函数调用运算符的类对象。

1.2 join()

join() 是 thread 类中的一个方法,其作用是:阻塞主线程,让主线程等待子线程执行完毕,然后子线程和主线程汇合,然后主线程再往下执行。

#include <iostream>
#include <thread>
using namespace std;

// 线程入口函数
void myThread()
{
	cout << "myThread begin" << endl;
	cout << "myThread running1" << endl;
	cout << "myThread running2" << endl;
	cout << "myThread running3" << endl;
	cout << "myThread running4" << endl;
	cout << "myThread running5" << endl;
	cout << "myThread running6" << endl;
	cout << "myThread end" << endl;
	return;
}

int main()
{
	thread td(myThread); // 创建了线程,线程入口函数是myThread(),myThread线程开始执行

	td.join(); // 阻塞主线程并等待myThread子线程执行完,当子线程执行完毕,这个join()函数就执行完毕,主线程继续往下执行

	cout << "hello world1" << endl;
	cout << "hello world2" << endl;
	cout << "hello world3" << endl;
	cout << "hello world4" << endl;
	cout << "hello world5" << endl;
	cout << "hello world6" << endl;

	return 0;
}

输出结果如下:

在这里插入图片描述

1.3 detach()

detach() 是 thread 类中的一个方法,其作用是:一旦 detach() 之后,与主线程关联的 thread 对象就会失去与主线程的关联,此时这个子线程就会驻留在后台运行(守护线程),这个子线程就相当于被 C++ 运行时库接管了,当这个子线程执行完成后,由运行时库负责清理该线程的相关资源。

一旦调用了 detach(),就不能再用 join() 了,否则系统会报异常。

#include <iostream>
#include <thread>
using namespace std;

// 线程入口函数
void myThread()
{
	cout << "myThread begin" << endl;
	cout << "myThread running1" << endl;
	cout << "myThread running2" << endl;
	cout << "myThread running3" << endl;
	cout << "myThread running4" << endl;
	cout << "myThread running5" << endl;
	cout << "myThread running6" << endl;
	cout << "myThread end" << endl;
	return;
}

int main()
{
	thread td(myThread); // 创建了线程,线程入口函数是myThread(),myThread线程开始执行

	td.detach(); // 主线程可以不等子线程结束就先结束,子线程不会被强制结束,而是可以继续运行,驻留在后台,由C++运行时库接管

	cout << "hello world1" << endl;
	cout << "hello world2" << endl;
	cout << "hello world3" << endl;
	cout << "hello world4" << endl;
	cout << "hello world5" << endl;
	cout << "hello world6" << endl;

	return 0;
}

输出结果如下:

在这里插入图片描述

1.4 joinable()

joinable() 是 thread 类中的一个方法,其作用是:判断线程是否可以成功使用 join() 或 detach()。

  • 如果返回 true,表示可以调用 join() 或 detach();
  • 如果返回 false,表示已经调用过 join() 或 detach(),不能再调用 join() 或 detach() 了。

2.函数对象作为线程函数

#include <iostream>
#include <thread>
using namespace std;

class A
{
public:
	int m_i;

	A(int i) : m_i(i)
	{
		cout << "构造函数执行,this = " << this << endl;
	}
	
	A(const A& a) : m_i(a.m_i)
	{
		cout << "拷贝构造函数执行,this = " << this << endl;
	}

	~A()
	{
		cout << "析构函数执行,this = " << this << endl;
	}
	
	// 线程入口函数
	void operator()(int num)
	{
		cout << "m_i = " << m_i << ",num = " << num << ",this = " << this << endl;
	}
};

int main()
{
	int i = 100;
	A a(i);

	thread td(a, 18);
	td.join();

	cout << "hello world1" << endl;
	cout << "hello world2" << endl;
	cout << "hello world3" << endl;

	return 0;
}

输出结果如下:

在这里插入图片描述

3.lambda表达式作为线程函数

#include <iostream>
#include <thread>
using namespace std;

int main()
{
    // 线程入口函数
	auto myThread = [] {
		cout << "myThread begin" << endl;
		cout << "myThread running1" << endl;
		cout << "myThread running2" << endl;
		cout << "myThread running3" << endl;
		cout << "myThread running4" << endl;
		cout << "myThread running5" << endl;
		cout << "myThread running6" << endl;
		cout << "myThread end" << endl;
	};

	thread td(myThread);
	td.join();

	cout << "hello world1" << endl;
	cout << "hello world2" << endl;
	cout << "hello world3" << endl;

	return 0;
}

输出结果如下:

在这里插入图片描述

4.类成员函数作为线程函数

#include <iostream>
#include <thread>
using namespace std;

class A
{
public:
	int m_i;
	
	A(int i) : m_i(i)
	{
		cout << "构造函数执行,this = " << this << endl;
	}
	
	A(const A& a) : m_i(a.m_i)
	{
		cout << "拷贝构造函数执行,this = " << this << endl;
	}

	~A()
	{
		cout << "析构函数执行,this = " << this << endl;
	}

	// 线程入口函数
	void work(int num)
	{
		cout << "m_i = " << m_i << ",num = " << num << ",this = " << this << endl;
	}
};

int main()
{
	A a(100);

	thread td(&A::work, a, 18);
	td.join();

	return 0;
}

输出结果如下:

在这里插入图片描述

5.向线程函数传递参数

关于向线程函数传递参数的具体细节,可以看下这篇文章:https://www.cnblogs.com/chen-cs/p/13056703.html

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【C++11多线程】线程的创建与结束:thread 的相关文章

随机推荐

  • 反向题在测试问卷信效度_九种方法筛选无效问卷及对研究设计的启示

    引言 随着网络及智能手机的普及 传统的一些纸笔测验渐渐被网络问卷所替代 网络问卷由于其便捷性 很大程度上方便了研究者和被试 2018年JOM一篇文章发现越来越多的研究者开始使用网络问卷收集数据 相关发表的文章也呈现逐年增加的趋势 参见Por
  • Linux——进程优先级

    1 什么是优先级 优先级和权限息息相关 权限的含义为能还是不能做这件事 而优先级则表示 你有权限去做 只不过是先去做还是后去做这件事罢了 2 为什么会存在优先级 优先级表明了狼多肉少的理念 举个例子 在日常生活中我们进行排队看医生 队列就是
  • CSDN如何转载别人的文章(快速转载)

    1 找到要转载的文章 用chrome浏览器打开 右键选择检查 2 在chrome中下方的框里找到对应的内容 html脚本中找到对应的节点 article content 选中节点 网页上被选中内容会被高亮显示 然后右键菜单选中 Copy g
  • gcc -l参数和-L参数

    l参数和 L参数 l参数就是用来指定程序要链接的库 l参数紧接着就是库名 那么库名跟真正的库文件名有什么关系呢 就拿数学库来说 他的库名是m 他的库文件名是libm so 很容易看出 把库文件名的头lib和尾 so去掉就是库名了 好了现在我
  • 查询引擎中的代码生成技术

    目录 一 背景 二 相关知识 2 1 Java虚拟机规范 2 1 1 数据类型 2 1 2 字节码指令 2 1 3 class文件格式 2 2 虚函数与CPU预测 2 3 查询引擎 火山模型 三 代码生成工具 3 1 动态编译器Janino
  • upload-labs初学者通关详解

    Pass 1 js验证绕过 首先在开始之前我们需要在我们导入的upload labs文件里面新建一个文件夹 方便我们上传php文件 打开第一关我们可以看见这个页面 我们将事先准好好的一句话木马文件传上去 可以看到提示 文件夹格式不正确 这时
  • 开放平台 文档

    QQ http wiki opensns qq com wiki E3 80 90QQ E7 99 BB E5 BD 95 E3 80 91add share
  • 朴素贝叶斯Naive Bayes-机器学习ML

    参考 1 统计学习方法 李航 2 先验概率与后验概率的区别 http blog csdn net ouyang linux007 article details 7566339 3 朴素贝叶斯方法 Naive Bayes 原理和实现 htt
  • hydra详细介绍及渗透利用大全(超细)

    hydra小白渗透路上必须掌握的工具 历史我就不介绍了百度上更详细 本内容仅供参考 切勿做违法犯罪 若出事一切与本人无关 请大家遵守网络安全法 祝大家早日成为安全界的大佬 Hydra 参数介绍 R 根据上一次进度继续破解 S 使用SSL协议
  • Spark 写入ElasticSearch报错类型整理

    1 Cannot determine write shards for authorRecommender Author likely its format is incorrect maybe it contains illegal ch
  • MyBatis核心配置文件详解、配置标签解析及SqlSession工厂对象

    一 MyBatis核心配置文件概述 1 MyBatis核心配置文件层级关系 2 MyBatis常用配置解析 1 environments标签 数据库环境的配置 支持多环境配置 其中 事务管理器 transactionManager 类型有两
  • CentOS虚拟机搭建

    下载centos的镜像 https www virtualbox org wiki Downloads 创建虚拟机内部虚拟网络 virtual box菜单 管理 gt 主机网络管理器 gt 创建 手动配置网卡并将ip地址设为192 168
  • 流批一体技术框架探索及在袋鼠云数栈中的实践

    一 关于流批一体数据仓库 流批一体是一种架构思想 这种思想说的是同一个业务 使用同一个sql逻辑 在既可以满足流处理计算同时也可以满足批处理任务的计算 从效率层面来说 批处理只能以t 1的形式呈现业务数据 流处理只能以t 0的形式呈现业务数
  • C# System.ArgumentNullException:“值不能为 null。Arg_ParamName_Name”

    弹窗显示异常报错如下所示 问题根因 添加tab顺序 修改图中的tab顺序 修改为
  • 全民农场服务器维护,全民农场1月22日更新了什么_全民农场1月22日更新维护内容介绍_游戏堡...

    全民农场今日更新之后将上线非常多精彩的活动内容 下面小编就为大家介绍一下全民农场1月22日更新维护内容 全民农场 将于1月22日12 00 18 30不停机更新 快来看看新的农场消息 1 全新惊喜一周活动开启 1月22日更新后 1月28日
  • HTTP抓包利器Fiddler基础及进阶教程(二)---- 手机端抓包+强制全局代理

    本文将进一步介绍Fiddler在移动端抓包的方法 一 配置Fiddler 二 查看当前IP 方式有很多种 选择运行 输入 cmd 在输入Ipconfig 三 验证是否配置成功 将上一步拿到的 IP Fiddler端口号 组成的链接用浏览器打
  • 读书笔记(2018年3月)-《卓有成效的管理者》总结

    1 善用时间 有效的管理者知道他们的时间用在什么地方 他们所能控制的时间非常有限 他们会有系统地工作 来善用这有限的时间 1 记录时间 记录时间耗用的实际情形 2 诊断时间 做有系统的时间管理 首先要找出什么事根本不必做 这些事做了也完全浪
  • Windows Server 2016抓取明文密码

    临时禁止Windows Defender REG ADD HKEY LOCAL MACHINE SOFTWARE Policies Microsoft Windows Defender v DisableAntiSpyware t REG
  • 原 QNetworkAccessManager实现curl上传表单文件

    心酸的过程我就不说了 直接上菜 如何用Qt实现 curl F file task plist http www fatjb com uploadfile QFile file m sTaskPlistPath if file exists
  • 【C++11多线程】线程的创建与结束:thread

    文章目录 1 普通函数作为线程函数 1 1 thread 1 2 join 1 3 detach 1 4 joinable 2 函数对象作为线程函数 3 lambda表达式作为线程函数 4 类成员函数作为线程函数 5 向线程函数传递参数 1