当前位置: 首页 > 编程日记 > 正文

C++多线程:thread类创建线程的多种方式

文章目录

      • 描述
      • 函数成员简介
      • 总结

描述

  • 头文件 <thread>

  • 声明方式:std::thread <obj>

  • 简介
    线程在构造关联的线程对象时立即开始执行,从提供给作为构造函数参数的顶层函数开始。如果顶层函数抛出异常,则调用 std::terminate。正如我们之前几篇说过的thread可以通过std::asyncstd::promise类对修改共享变量,并将返回值传递给调用方。如果共享变量在该过程中需要进行同步,则就需要我们说过的std::mutexstd::condition_variable

    std::thread不支持拷贝构造和赋值,如果需要将当前t1 对象赋值给t2对象,需要通过移动赋值std::move,即将t1的地址以及内容全部赋值给t2对象才行。

函数成员简介

  • 构造函数(创建线程的多种方式)
    a. 类对象的拷贝创建线程
    b. 类对象的引用创建线程
    c. 移动复制std::move对象创建线程
    d. 临时创建的对象创建线程
    e. 函数名创建线程
    f. lamda函数创建线程
    g. 类对象的拷贝的成员函数 创建线程
    h. 类对象的地址的成员函数 创建线程
    #include <iostream>
    #include <utility>
    #include <thread>
    #include <chrono>void f1(int n)
    {for (int i = 0; i < 5; ++i) {std::cout << "Thread 1 executing\n";++n;std::this_thread::sleep_for(std::chrono::milliseconds(10));}
    }void f2(int& n)
    {for (int i = 0; i < 5; ++i) {std::cout << "Thread 2 executing\n";++n;std::this_thread::sleep_for(std::chrono::milliseconds(10));}
    }class foo
    {
    public:void bar(){for (int i = 0; i < 5; ++i) {std::cout << "Thread 3 executing\n";++n;std::this_thread::sleep_for(std::chrono::milliseconds(10));}}int n = 0;
    };class baz
    {
    public:void operator()(int n){for (int i = 0; i < 5; ++i) {std::cout << "Thread 4 executing\n";++n;std::this_thread::sleep_for(std::chrono::milliseconds(10));}}int n = 0;
    };int main()
    {int n = 0;foo f;baz b;std::thread t1; // t1 is not a threadstd::thread t2(f1, n + 1); // 普通函数名创建线程,传递函数参数为值std::thread t3(f2, std::ref(n)); // 普通函数名创建线程,传递函数参数为引用std::thread t4(std::move(t3)); // 类对象的移动赋值,使用std::movestd::thread t5(&foo::bar, &f); // 类对象的拷贝的地址的成员函数std::thread t6(b,6); // 类对象创建线程,默认执行operator ()函数std::thread t7([](int x){return x*x;},6);//lamda函数创建子线程std::thread t8(std::ref(b),6);//类对象的引用创建std::thread t9(baz(),6);//临时对象创建t2.join();t4.join();t5.join();t6.join();t7.join();t8.join();t9.join();std::cout << "Final value of n is " << n << '\n';std::cout << "Final value of foo::n is " << f.n << '\n';
    }
    
    输出如下,由于输出为线程间交叉执行,输出会有点乱:
    Thread 2 executing
    Thread 4 executing
    Thread 1 executing
    Thread 3 executing
    Thread 4 executing
    Thread 4 executing
    Thread 2 executing
    Thread 1 executing
    Thread 3 executing
    Thread 4 executing
    Thread 4 executing
    Thread 4 executing
    Thread 2 executing
    Thread 1 executing
    Thread 4 executing
    Thread 3 executing
    Thread 4 executing
    Thread 4 executing
    Thread 2 executing
    Thread 4 executing
    Thread 4 executing
    Thread 1 executing
    Thread 3 executing
    Thread 4 executing
    Thread 2 executing
    Thread 4 executing
    Thread 4 executing
    Thread 3 executing
    Thread 4 executing
    Thread 1 executing
    Final value of n is 5
    Final value of foo::n is 5
    
  • std::thread::joinable检查 thread 对象是否标识活跃的执行线程,是返回true,否则返回false
    如下代码
    #include <iostream>
    #include <thread>
    #include <chrono>void foo()
    {std::this_thread::sleep_for(std::chrono::seconds(1));
    }int main()
    {//刚创建好的线程对象是不活跃的std::thread t;std::cout << "before starting, joinable: " << std::boolalpha << t.joinable()<< '\n';//创建线程并执行代码,但未合并,则它是活跃的t = std::thread(foo);std::cout << "after starting, joinable: " << t.joinable() << '\n';//线程合并之后变为不活跃的t.join();std::cout << "after joining, joinable: " << t.joinable() << '\n';
    }
    
    输出如下:
    before starting, joinable: false
    after starting, joinable: true
    after joining, joinable: false
    
  • std::thread::join阻塞线程成员,直到线程函数代码执行完毕返回
    代码如下:
    #include <iostream>
    #include <thread>
    #include <chrono>void foo()
    {std::this_thread::sleep_for(std::chrono::seconds(1));
    }void bar()
    {std::this_thread::sleep_for(std::chrono::seconds(1));
    }int main()
    {std::cout << "starting first helper...\n";std::thread helper1(foo);std::cout << "starting second helper...\n";std::thread helper2(bar);std::cout << "waiting for helpers to finish..." << std::endl;helper1.join();helper2.join();std::cout << "done!\n";
    }
    
    输出如下:
    starting first helper...
    starting second helper...
    waiting for helpers to finish...
    done!
    
  • std::thread::detach从 thread 对象分离执行的线程,允许执行独立地执行线程
    一旦线程退出,则释放所有分配的资源。
    如下代码:
    #include <iostream>
    #include <chrono>
    #include <thread>void independentThread() 
    {std::cout << "Starting concurrent thread.\n";std::this_thread::sleep_for(std::chrono::seconds(2));std::cout << "Exiting concurrent thread.\n";
    }void threadCaller() 
    {std::cout << "Starting thread caller.\n";std::thread t(independentThread);//这里调用detach,则线程t将独立执行,所以当前线程的输出会早于t线程的输出t.detach();std::this_thread::sleep_for(std::chrono::seconds(1));std::cout << "Exiting thread caller.\n";
    }int main() 
    {threadCaller();std::this_thread::sleep_for(std::chrono::seconds(5));
    }
    
    输出如下:
    Starting thread caller.
    Starting concurrent thread.
    Exiting thread caller.
    Exiting concurrent thread.
    
  • std::thread::swap交换两个线程的对象的文件句柄
    代码如下:
    #include <iostream>
    #include <thread>
    #include <chrono>void foo()
    {std::this_thread::sleep_for(std::chrono::seconds(1));
    }void bar()
    {std::this_thread::sleep_for(std::chrono::seconds(1));
    }int main()
    {std::thread t1(foo);std::thread t2(bar);std::cout << "thread 1 id: " << t1.get_id() << std::endl;std::cout << "thread 2 id: " << t2.get_id() << std::endl;使用boost的swap和thread类封装的swap函数效果类似,都会交换线程的文件句柄std::swap(t1, t2);std::cout << "after std::swap(t1, t2):" << std::endl;std::cout << "thread 1 id: " << t1.get_id() << std::endl;std::cout << "thread 2 id: " << t2.get_id() << std::endl;t1.swap(t2);std::cout << "after t1.swap(t2):" << std::endl;std::cout << "thread 1 id: " << t1.get_id() << std::endl;std::cout << "thread 2 id: " << t2.get_id() << std::endl;t1.join();t2.join();
    }
    
    输出如下:
    thread 1 id: 0x70000f1e9000
    thread 2 id: 0x70000f26c000
    after std::swap(t1, t2):
    thread 1 id: 0x70000f26c000
    thread 2 id: 0x70000f1e9000
    after t1.swap(t2):
    thread 1 id: 0x70000f1e9000
    thread 2 id: 0x70000f26c000
    

总结

本文介绍了C++的多线程类thread的基本使用,在前面几篇文章的描述之下对C++多线程编程有了基本的使用能力。面向对象的编程让线程类在并发编程中发挥出了精妙的高效便捷优势,今后需要多多实践与体会C++并发编程的妙处。

相关文章:

C C++的编译过程详解

C/C编译过程C/C编译过程主要分为4个过程1) 编译预处理2) 编译、优化阶段3) 汇编过程4) 链接程序一、编译预处理&#xff08;1&#xff09;宏定义指令&#xff0c;如#define Name TokenString&#xff0c;#undef等。 对于前一个伪指令&#xff0c;预编译所要做的是将程序中的所有…

python queue 调试_学Python不是盲目的,是有做过功课认真去了解的

有多少伙伴是因为一句‘人生苦短&#xff0c;我用Python’萌生想法学Python的&#xff01;我跟大家更新过很多Python学习教程普及过多次的Python相关知识&#xff0c;不过大家还是还得计划一下Python学习路线&#xff01;Python入门前&#xff0c;你必须得知道这些&#xff0c;…

嘿嘿 刚刚进来 记录下

大家好&#xff0c;小弟刚刚进来&#xff0c;记录一下&#xff0c;发现这个网站真是太好了&#xff01;&#xff01;转载于:https://blog.51cto.com/wikowin/1112039

Oracle数据库查看表空间是否为自增的

表空间是有数据文件组成的&#xff0c;所以看表空间是否自增即看数据文件&#xff0c;如下查自增的表空间&#xff1a; select tablespace_name,file_name,autoextensible from dba_data_files where autoextensibleYES; autoextensible: YES/NO 即表示是否自增。 转载于:https…

C++多线程:异步操作std::async和std::promise

文章目录std::async简介使用案例std::promise简介成员函数总结之前的文章中提到了C多线程中的异步操作机制 C 多线程&#xff1a;future 异步访问类&#xff08;线程之间安全便捷的数据共享)&#xff0c;接下来分享关于异步操作中 async和 promise的相关使用总结。std::async …

5如何将表格的一行数据清空_微信公众号推文中如何自定义添加表格?

微信公众号发的图文消息里经常需要有表格&#xff0c;因为表格进行数据展现更直观明了&#xff0c;所以接下来就给大家分享一下如何自定义添加表格。打开小蚂蚁编辑器&#xff0c;在编辑区点击鼠标右键&#xff0c;在出现的选项中选择【插入表格】。系统会默认添加一个5行5列的…

基于visual Studio2013解决面试题之0901奇偶站队

&#xfeff;&#xfeff;&#xfeff;题目解决代码及点评/*给定一个存放整数的数组&#xff0c;重新排列数组使得数组左边为奇数&#xff0c;右边为偶数 解决方法&#xff1a;两边同时遍历&#xff0c;如果遇到左边偶数或者右边基数&#xff0c;则交换 */#include <iostrea…

联想架构调整:智能手机业务很重要

1月5日&#xff0c;杨元庆宣布联想集团进行组织架构调整。将联想旗下业务拆分为两个新的端到端业务集团—— Lenovo 业务集团和 Think 业务集团。杨元庆在内部邮件如是说:“Lenovo业务集团(Lenovo Business Group&#xff0c;简称LBG)&#xff0c;由刘军领军&#xff0c;致力于…

activiti5/6 系列之--BpmnModel使用

BpmnModel对象&#xff0c;是activiti动态部署中很重要的一个对象&#xff0c;如果BpmnModel对象不能深入的理解&#xff0c;那可能如果自己需要开发一套流程设计器&#xff0c;使用bpmn-js使用前端或者C/S展现流程流转而不是使用工作流引擎&#xff0c;就显得力不从心。例如&a…

C++多线程:package_task异步调用任何目标执行操作

文章目录描述函数成员及使用总结我们上一篇描述关于C多线程中的异步操作相关库( async和 promise)&#xff0c;本节将分享c标准库中最后一个多线程异步操作库 package_task的学习笔记。描述 头文件 <future> 声明方式: template< class R, class ...Args > class …

ICE BOX 配置,使用----第一篇

一 理论部分 (1) 为什么要使用icebox? icebox server代替了通常的server. icebox是为了方便集中管理多个ice服务而建立的。 它通过使用icebox服务器&#xff0c;把ice服务注册进去&#xff0c;从而建立联系。 所以它除了建立传统的ice服务器&#xff0c;ice客户端&#xff0c;…

测试打桩_DNF:CEO实测旭旭宝宝红眼,打桩高达2494E,伤害超越狂人剑魂

对于红眼这个职业&#xff0c;旭旭宝宝倾注了太多的心血&#xff0c;耗资几千万打造而成。虽然&#xff0c;作为固伤职业&#xff0c;在伤害方面&#xff0c;不及剑魂和剑帝这类百分比&#xff0c;但因人数颇多&#xff0c;从而被广泛关注。而今&#xff0c;旭旭宝宝的红眼&…

122112_1452_Word1

122112_1452_Word1转载于:https://www.cnblogs.com/joshuali/archive/2013/01/11/4339303.html

C++ 多线程:时间控制

C多线程库中的各个子库都有各自的时间控制方式&#xff0c;依此来进行多线程程序运行中cpu资源的精确控制。 使用std::chrono时间库可以提供微妙、毫秒、秒及以上的时间取用,并且能够获取当前系统时间。 如下代码 #include <iostream> #include <fstream> #inclu…

array用法 numpy_NumPy总结(基础用法)

numpy可以说是Python运用于人工智能和科学计算的一个重要基础&#xff0c;近段时间恰好学习了numpy&#xff0c;pandas&#xff0c;sklearn等一些Python机器学习和科学计算库&#xff0c;因此在此总结一下常用的用法。引入numpy库的方式&#xff1a;import numpy as np1、numpy…

python 字符串 转 dict

比直接eval更好的方法>>>import ast >>>ast.literal_eval("{muffin : lolz, foo : kitty}") {muffin:lolz,foo:kitty} 用 json 遇到问题&#xff1a; >>> import json json.loads({"x": 1,"y":2}) {uy: 2, ux: 1…

rhino-java中调用javascript

2019独角兽企业重金招聘Python工程师标准>>> 在有些情况下需要在java里面执行javascript&#xff0c;这时rhino就可以帮忙了。mozilla的一个开源产品。 官网https://developer.mozilla.org/en-US/docs/Rhino 之前的一篇博客http://my.oschina.net/yybear/blog/101…

HDU 2566 统计硬币

统计硬币 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 9633 Accepted Submission(s): 6505 Problem Description 假设一堆由1分、2分、5分组成的n个硬币总面值为m分&#xff0c;求一共有多少种可能的组合方式&…

linux C 多线程编程

文章目录多线程的一些小知识&#xff1a;1创建线程 pthread_create2线程挂起 pthread_join3线程终止 pthread_exit4线程分离 pthread_detach5线程取消 pthread_cancel线程同步 pthread_mutex_t互斥变量我们在写linux的服务的时候&#xff0c;经常会用到linux的多线程技术以提高…

JavaSE replaceAll 方法

private String srcStr "index\\.php\\?action";//要替换的原字符串 private String destStr "index.php?<{\\$LANGUAGE_TYPE}>action";//目的字符串 注意.和?都要转义&#xff0c;因此需要在前面添加两个反斜杠。 关于第二个参数&#xff0c;$…

elementui datetimepicker 移动端_在 Gitee 收获 2.5K Star,前后端分离的 RuoYi 它来了

作为 2019 年 Gitee 上最受欢迎的开源项目&#xff0c;权限管理系统 RuoYi 已经在 Gitee 上获得了超过 11K 的 Star。 这次作者若依推出了基于 SpringBoot Vue Element UI 的前后端分离版本的 RuoYi-Vue&#xff0c;方便有前后端分离开发需求的同学使用。项目名称&#xff1a…

用MyEclipse开发Spring入门

1 新建一个项目 File----->New ----->Project 在出现的对话框中选择 MyEclipse 下的 Web Project&#xff0c;在Project Name 输入mySpring1&#xff0c;其他的选项默认&#xff0c;再点Finish完成&#xff1b; 2 加入Spring 包 在myspring1 项目上点右键&#xff0c;选…

带你轻而易举的学习python——八皇后问题

首先我们来看一下这个著名的八皇后问题 八皇后问题&#xff1a;在88格的国际象棋上摆放八个皇后&#xff0c;使其不能互相攻击&#xff0c;即任意两个皇后都不能处于同一行、同一列或同一斜线上&#xff0c;问有多少种摆法。 在这个问题提出之后人们又将它扩展到了nn格的棋盘摆…

ubuntu18.04.1内核升级至5.0.0-25版本

ubuntu18.04操作系统版本先已支持在线的内核版本升级&#xff0c;到目前为止18.04发布版已经拥有三个小版本了1,2,3。 其中18.04.01和18.04.03版本&#xff0c;安装好之后默认的是4.15内核版本&#xff0c;但是默认支持在线安装4.18和5.0.0内核版本。 具体升级步骤如下&#x…

输出n行杨辉三角数

1 /*2 输出n行杨辉三角数 3 输入n&#xff0c;n是1&#xff5e;100之间的整数 4 */5 #include<stdio.h>6 int main()7 {8 int a[100],b[100];9 int i,j; 10 int n; 11 scanf("%d",&n); 12 if(n1) 13 { 14 printf("1\…

怎么扫描_打印机上扫描仪怎么用 打印机上扫描仪使用及添加方法

打印机是生活中常用的打印设备&#xff0c;主要用于连接 电脑 打印电脑上的文件&#xff0c;方便办公。对于第一次使用打印机的朋友可能还不是很熟悉如何使用&#xff0c;比如打印机上 扫描仪 怎么用&#xff1f;怎么添加打印机扫描仪&#xff1f;下面小编就来为大家介绍下吧。…

java 调用webservice的各种方法总结

http://www.blogjava.net/zjhiphop/archive/2009/04/29/webservice.html 现在webservice加xml技术已经逐渐成熟&#xff0c;但要真正要用起来还需时日!! 由于毕业设计缘故&#xff0c;我看了很多关于webservice方面的知识&#xff0c;今天和大家一起来研究研究webservice的…

vc++图像保存,重绘

新建mfc应用程序&#xff0c;单文档 增加绘图 分别增加命令响应 添加成员变量UINIT 图形可以运行&#xff0c;如何保存呢&#xff1f;&#xff08;一个集合类&#xff0c;CPtArt&#xff09; 用一个类的对象来保存一个图形的三个要素 所以插入一个新的类&#xff08;通常的类&a…

linux 进程内存分布及 堆分配和栈分配的特点

文章目录进程内存空间分布size命令查看内存分布堆方式内存分配和栈方式内存分配比较使用stap 深入追踪malloc逻辑进程内存空间分布 一个程序的内存空间主要如下&#xff1a; 代码段(text segment)&#xff1a;只读权限&#xff1b;常是指用来存放程序执行代码的一块内存区域&…

echarts 坐标自适应_echarts 同一页面,多个图表 页面大小自适应

// 路径配置require.config({paths: {echarts: ./js}});// 使用require([echarts,echarts/chart/line, // 折线图echarts/chart/bar // 柱状图],function (ec) {var myChart ec.init(document.getElementByIdx_x(main));var myChartx ec.init(document.getElementByIdx_x(main…