原始C++标准仅支持单线程编程。新的C++标准(称为C++11或C++0x)于2011年发布。在C++11中,引入了新的线程库。因此运行本文程序需要C++至少符合C++11标准。

1 创建线程的三种不同方式

在本章中,我们将讨论如何使用std::thread在C++11中创建线程。

在每个C++应用程序中,都有一个默认的主线程,即main()函数。在C++11中,我们可以通过创建std::thread类的对象来创建其他线程。每个std::thread对象都可以与一个线程关联。因此我们需要引入头文件为:

#include <thread>

那么std::thread在构造函数中接受什么?我们可以在std::thread对象上附加一个回调,该回调将在新线程启动时执行。这些回调可以是:

  1. 函数指针
  2. 函数对象
  3. Lambda函数

1.1 创建线程

可以这样创建线程对象:

std::thread thObj(<CALLBACK>);

新线程将在创建新对象后立即启动,并将与启动该线程的线程并行执行传递的回调。而且,任何线程都可以通过在该线程的对象上调用join()函数来等待另一个线程退出。

让我们看一个示例,其中主线程将创建一个单独的线程。创建此新线程后,主线程将在控制台上打印一些数据,然后等待新创建的线程退出。我们使用三种不同的回调机制来实现上述功能。

  1. 使用函数指针创建线程
#include <thread>
#include <iostream> using namespace std; void thread_function()
{
for (int i = 0; i < 10000; i++);
std::cout << "thread function Executing" << std::endl;
} int main()
{
// 创建线程
std::thread threadObj(thread_function);
for (int i = 0; i < 10000; i++);
std::cout << "Display From MainThread" << std::endl;
// 等待线程的结束
threadObj.join();
std::cout << "Exit of Main function" << std::endl;
return 0;
}

输出为:

Display From MainThreadthread function Executing

Exit of Main function
  1. 使用函数对象创建线程
#include <iostream>
#include <thread> class DisplayThread
{
public:
void operator()()
{
for (int i = 0; i < 10000; i++);
std::cout << "Display Thread Executing" << std::endl;
}
}; int main()
{
std::thread threadObj((DisplayThread()));
for (int i = 0; i < 10000; i++);
std::cout << "Display From Main Thread " << std::endl;
std::cout << "Waiting For Thread to complete" << std::endl;
threadObj.join();
std::cout << "Exiting from Main Thread" << std::endl;
return 0;
}

输出为:

Display Thread ExecutingDisplay From Main Thread
Waiting For Thread to complete Exiting from Main Thread
  1. 使用Lambda函数创建线程
#include <iostream>
#include <thread> int main()
{
int x = 9;
std::thread threadObj([] {
for (int i = 0; i < 10000; i++)
std::cout << "Display Thread Executing" << std::endl;
}); for (int i = 0; i < 10000; i++)
std::cout << "Display From Main Thread" << std::endl; threadObj.join();
std::cout << "Exiting from Main Thread" << std::endl;
return 0;
}

输出为:

Display Thread ExecutingDisplay From Main Thread

Exiting from Main Thread

1.2 区分线程

每个std::thread对象都有一个关联的ID,我们可以使用成员函数来获取,给出关联的thread对象的ID。

std::thread::get_id()

要获取当前线程使用的标识符,即

std::this_thread::get_id()

如果std::thread对象没有关联的线程,则get_id()将返回默认构造的std::id对象,即“没有任何线程”。std::id是一个Object,也可以在控制台上进行比较和打印。让我们看一个例子。

#include <iostream>
#include <thread> void thread_function()
{
std::cout << "Inside Thread::ID  = " << std::this_thread::get_id() << std::endl;
}
int main()
{
std::thread threadObj1(thread_function);
std::thread threadObj2(thread_function); if (threadObj1.get_id() != threadObj2.get_id())
std::cout << "Both Threads have different IDs" << std::endl; std::cout << "From Main Thread::ID of Thread 1 = " << threadObj1.get_id() << std::endl;
std::cout << "From Main Thread::ID of Thread 2 = " << threadObj2.get_id() << std::endl; threadObj1.join();
threadObj2.join();
return 0;
}

输出为:

Inside Thread::ID? = 14756
Inside Thread::ID? = 15500
Both Threads have different IDs
From Main Thread::ID of Thread 1 = 14756
From Main Thread::ID of Thread 2 = 15500

1.3 参考

https://thispointer.com//c-11-multithreading-part-1-three-different-ways-to-create-threads/

[编程基础] C++多线程入门1-创建线程的三种不同方式的更多相关文章

  1. Java创建线程的三种主要方式

    Java创建线程的主要方式 一.继承Thread类创建 通过继承Thread并且重写其run(),run方法中即线程执行任务.创建后的子类通过调用 start() 方法即可执行线程方法. 通过继承Th ...

  2. Java并发编程:Java创建线程的三种方式

    目录 引言 创建线程的三种方式 一.继承Thread类 二.实现Runnable接口 三.使用Callable和Future创建线程 三种方式的对比 引言 在日常开发工作中,多线程开发可以说是必备技能 ...

  3. Java并发编程(二)创建线程的三种方法

    进程与线程 1.  进程 进程和代码之间的关系就像音乐和乐谱之间的关系一样,演奏结束的时候音乐就不存在了但乐谱还在:程序执行结束的时候进程就消失了但代码还在,而计算机就是代码的演奏家. 2. 线程 线 ...

  4. 《Java多线程面试题》系列-创建线程的三种方法及其区别

    1. 创建线程的三种方法及其区别 1.1 继承Thread类 首先,定义Thread类的子类并重写run()方法: package com.zwwhnly.springbootaction.javab ...

  5. 0036 Java学习笔记-多线程-创建线程的三种方式

    创建线程 创建线程的三种方式: 继承java.lang.Thread 实现java.lang.Runnable接口 实现java.util.concurrent.Callable接口 所有的线程对象都 ...

  6. java创建线程的三种方式及其对比

    第一种方法:继承Thread类,重写run()方法,run()方法代表线程要执行的任务.第二种方法:实现Runnable接口,重写run()方法,run()方法代表线程要执行的任务.第三种方法:实现c ...

  7. AJPFX总结java创建线程的三种方式及其对比

    Java中创建线程主要有三种方式: 一.继承Thread类创建线程类 (1)定义Thread类的子类,并重写该类的run方法,该run方法的方法体就代表了线程要完成的任务.因此把run()方法称为执行 ...

  8. java创建线程的三种方式及其对照

    Java中创建线程主要有三种方式: 一.继承Thread类创建线程类 (1)定义Thread类的子类.并重写该类的run方法,该run方法的方法体就代表了线程要完毕的任务.因此把run()方法称为运行 ...

  9. java创建线程的三种方法

    这里不会贴代码,只是将创建线程的三种方法做个笼统的介绍,再根据源码添加上自己的分析. 通过三种方法可以创建java线程: 1.继承Thread类. 2.实现Runnable接口. 3.实现Callab ...

随机推荐

  1. Docker容器虚拟化

    Docker容器虚拟化 目录 Docker容器虚拟化 虚拟化网络 单节点容器间通信 不同节点容器间通信 虚拟化网络 Network Namespace 是 Linux 内核提供的功能,是实现网络虚拟化 ...

  2. CCS 2022 极客少年挑战赛 writeup

    ​ 目录 题目一DSDS 操作内容: 题目二 easy_re 操作内容: flag值: 题目三 1+1=all 解题过程 题目一DSDS 操作内容: 开环境然后进入网址在网址后./目录 进入目录得到个 ...

  3. Selenium+Python系列(三) - 常见浏览器操作

    写在前面 上篇文章为大家分享了自动化测试中,常见元素定位的操作. 今天再次读文章,居然忘记了大家特别喜欢的CSS和Xpath定位操作分享,这怎么能行呢? 马上安利,感兴趣的同学去参考下面链接: CSS ...

  4. .NET7 gRPC JSON转码+OpenAPI

    gRPC JSON转码 gRPC JSON 转码允许浏览器应用调用 gRPC 服务,就像它们是使用 JSON 的 RESTful API 一样. 浏览器应用不需要生成 gRPC 客户端或了解 gRPC ...

  5. Oracle 表空间常用操作

    aliases: [Oracle表空间] tags:      [数据库,Oracle,Blog] summary: [Oracle表空间常用操作,包括查询.分析.扩容.删除.优化等] date:   ...

  6. 少走点弯路:Wiki.js 通过 Generic OAuth2 进行身份验证

    Wiki.js介绍 Wiki.js 是一个开源的百科全书系统,可以用来搭建自己的知识库.文档库等. 官网 | GitHub 后续内容中的Wiki.js会用Wiki代替. 本文环境:Wiki 2.5.2 ...

  7. Go语言核心36讲31

    我们在前两篇文章中讨论了互斥锁.读写锁以及基于它们的条件变量,先来总结一下. 互斥锁是一个很有用的同步工具,它可以保证每一时刻进入临界区的goroutine只有一个.读写锁对共享资源的写操作和读操作则 ...

  8. Go语言核心36讲23

    我在上两篇文章中,详细地讲述了Go语言中的错误处理,并从两个视角为你总结了错误类型.错误值的处理技巧和设计方式. 在本篇,我要给你展示Go语言的另外一种错误处理方式.不过,严格来说,它处理的不是错误, ...

  9. 第三方模块的下载与使用、requests模块、爬取链家二手房数据、openpyxl模块、hashlib加密模块

    目录 第三方模块的下载与使用 下载第三方模块可能会出现的问题 网络爬虫模块之requests模块 网络爬虫实战之爬取链家二手房数据 自动化办公领域之openpyxl模块 第三方模块的下载与使用 第三方 ...

  10. 数电第四周周结_by_yc

    数电第四周周结 1.赋值语句 基本概念: 连续赋值:   1.连续赋值不能出现在过程块(如initial,always)中间:   2.连续赋值语句之间是并行的:   3. 只能对wire型变量进行赋 ...