当前课程知识点:基于Linux的C++ >  第十四讲 线程编程 >  14.12 C++11线程库(四) >  LinuxCPP1412

返回《基于Linux的C++》慕课在线视频课程列表

LinuxCPP1412在线视频

LinuxCPP1412

下一节:LinuxCPP1413

返回《基于Linux的C++》慕课在线视频列表

LinuxCPP1412课程教案、知识点、字幕

这一讲最后一个知识点是期许与承诺

我们刚才不说了吗

为了支持跨平台啊

thread那个类啊

它是没有属性的

保存不了线程的返回值

同时呢也没有办法设置

它的线程属性状态

所有的这些细节信息

在thread这个类里都是不存在的

当然也不是说你用thread这样的类

构造的那个线程对象

它真地不能返回结果

不 它实际上是可以返回结果的

事实上我们有三种手段

可以返回结果

一个是使用指针型式的函数参数

把这个传给那个线程函数

指针本身 它的目标数据对象

就可以把结果带回来嘛

就可以充当返回值的作用

这本身是可以的

第二个你可以使用期许

第三个你可以使用承诺

期许和承诺就是C++11标准库

为我们提供的新的机制

我们首先来看指针型式的参数

怎么把这个线程的结果带回来

我们这里把这个Worker这个劳动类

重新定义成一个模板

它能够处理的是T型的任务

处理T型数据对象

这是Worker 这是我们的模板

类模板 我们来看主函数

我们定义

能够容纳8个三元组的向量v

为什么要这么定义呢

就是我们这个程序要启动好几个线程

来执行我们的线程函数

每一个线程 它执行的那个线程函数

虽然是一样的

但是它是在不同的对象上

做这个线程函数的

所以要有对应的劳工对象

还有呢 每一个线程

得到的结果是不一样的

所以它还有一个对应的返回值信息

那现在我们就知道了

一个线程对象和这个线程对象中

要做线程函数的真正的那个劳工对象

和那个劳工对象

做完这个线程函数之后得到的结果

这三者是一体的

那我们就可以使用C++11标准库里边

给我们提供的tuple这个三元组

来定义一个三元组的模板类

std::tuple〈Worker〈int〉*, int std::thread*〉

用它定义一个三元组

然后作为vector的元素的型

也就是vector这个模板的实际参数

构造一个向量v

初始化成8个元素

做的就是这个东西

我们初始化这个三元组

调用std::make_tuple()

来构造这个三元组

动态构造一个Worker〈int〉

作为第一个参数传进去

第二个参数是那个

劳工线程的返回值嘛 传0

第三个参数是那个线程对象嘛

我们还没构造呢

传空指针 然后我们for循环

输出“No.”、i 第几号线程

结果是什么呢

结果std::get〈1〉(v[i])

std::get()是标准库里面替我们提供的

想获取一个特定的元组的

第几号元的那个函数

它实际上是一个模板了

传1 表示取这个元组的一号元

三元组的一号元是哪一个呢

它顺次编号嘛

第一个是0号元

第二个是1号元

第三个是1号元嘛

它就顺次编号

一号元就是它那个返回值

第几个线程的一号元

也就是线程函数的返回值

先打印一遍

现在什么都没有

全是0 你就打印出来了

现在我们创建8个线程

分别进行计算

auto f 自动变量f

把它初始化成std::bind()

这是一个函数 绑定它

把这个函数绑定成什么呢

绑定成Worker〈int〉::ThreadFunc这个线程函数

这是一个类的成员函数

我要绑定它

绑定到std::get〈0〉(v[i])上

就绑定到这个向量的第i号元

第0号三元组元素上

这个向量的每个元素不是一个三元组吗

这个三元组每一个顶头的0号元

不是我们这个劳工对象吗

指向这个劳工对象的指针

所以我们就把它

绑定到这个类的成员函数上

这是std::bind()这个函数

以前我们已经这么用过了

只不过没有第三个参数而已

前两个参数不都是这么用的吗

OK 我们就把它绑定

为什么要传第三个参数呢

看上去好怪 std::placeholders::_1

我们待会再解释

现在我们构造线程newstd::thread

括号里第一个参数传我们绑定的

那个线程函数f

第二个参数传那个线程函数的参数

参数是什么呢

参数就是返回值 std::get〈1〉(v[i])

取的就是那个三元组的1号元

那个int 返回值

把它的地址作为附加参数传进去

构造这个线程 动态构造出来的

然后我把这个动态构造出来的

一个线程的地址

写入三元组的2号元

std::get〈2〉(v[i])

这就是取那个三元组的二号元

把新构造的这个线程写进去

这个线程在执行的时候

就会传这个函数参数

这个函数的参数

是那个线程函数的第几个呢

这里写着呢

std::placeholders::_1

我们就在调用std::bind()

这个函数的时候

绑定了这个线程函数参数传递的细节

就是说我要将

在构造这个线程对象的时候

传递的这个附加参数

作为绑定的那个线程的

函数的第一个参数传给它

这个就叫占位符

placeholders 叫占位符

一号占位符_1

表示占一号位置 就这个意思

你后面跟着这个参数

就将作为那个绑定函数的第一个参数

这个时候不是从0开始计数了

就是它的第一个参数

你如果后面还有一个参数

这后面就要写

std::placeholders::_1,std::placeholders::_2

一号占位符 二号占位符

那后两个参数就会作为第一个参数

作为第二个参数传进去

做的就是这个事情 很神奇

就把我们构造线程的时候

那个附加参数

就传给我们类的成员函数

然后它就能够执行

然后就能够把这个结果

写到我们这个向量里的元素里的

那个三元组的中间那个位置

也就是1号元 写for循环

等待我们的线程结束

所有的线程都是通过

std::get〈2〉(v[i])得到的

得到这个线程

指向这个线程对象的指针

然后我们箭头join() 等待它结束

然后我们就可以销毁劳工对象

销毁线程对象

最终输出我们的程序计算的结果

这个时候你就会看到

所有的数据都出来了

基于Linux的C++课程列表:

第一讲 C/C++基本语法元素

-1.1 提纲

--LinuxCPP0101

-1.2 程序设计的基本概念

--LinuxCPP0102

-1.3 简单C/C++程序介绍

--LinuxCPP0103

-1.4 程序设计的基本流程

--LinuxCPP0104

-1.5 基本语法元素

--LinuxCPP0105

-1.6 程序设计风格

--LinuxCPP0106

-1.7 编程实践

--LinuxCPP0107

-第一讲 C/C++基本语法元素--编程实践提交入口

第二讲 程序控制结构

-2.1 提纲

--LinuxCPP0201

-2.2 结构化程序设计基础

--LinuxCPP0202

-2.3 布尔数据

--LinuxCPP0203

-2.4 分支结构

--LinuxCPP0204

-2.5 break语句

--LinuxCPP0205

-2.6 循环结构

--LinuxCPP0206

-2.7 编程实践

--LinuxCPP0207

-第二讲 程序控制结构--编程实践提交入口

第三讲 函数

-3.1 提纲

--LinuxCPP0301

-3.2 函数声明、调用与定义

--LinuxCPP0302

-3.3 函数调用栈框架

--LinuxCPP0303

-3.4 编程实践

--LinuxCPP0304

-第三讲 函数--编程实践提交入口

第四讲 算法

-4.1 提纲

--LinuxCPP0401

-4.2 算法概念与特征

--LinuxCPP0402

-4.3 算法描述

--LinuxCPP0403

-4.4 算法设计与实现

--LinuxCPP0404

-4.5 递归算法(一)

--LinuxCPP0405

-4.6 递归算法(二)

--LinuxCPP0406

-4.7 容错与计算复杂度

--LinuxCPP0407

-4.8 编程实践

--LinuxCPP0408

-第四讲 算法--编程实践提交入口

第五讲 程序组织与开发方法

-5.1 提纲

--LinuxCPP0501

-5.2 库与接口

--LinuxCPP0502

-5.3 随机数库(一)

--LinuxCPP0503

-5.4 随机数库(二)

--LinuxCPP0504

-5.5 作用域与生存期

--LinuxCPP0505

-5.6 典型软件开发流程(一)

--LinuxCPP0506

-5.7 典型软件开发流程(二)

--LinuxCPP0507

-5.8 编程实践

--LinuxCPP0508

-第五讲 程序组织与开发方法--编程实践提交入口

第六讲 复合数据类型

-6.1 提纲

--LinuxCPP0601

-6.2 字符

--LinuxCPP0602

-6.3 数组(一)

--LinuxCPP0603

-6.4 数组(二)

--LinuxCPP0604

-6.5 结构体

--LinuxCPP0605

-6.6 编程实践

--LinuxCPP0606

-第六讲 复合数据类型--编程实践提交入口

第七讲 指针与引用

-7.1 提纲

--LinuxCPP0701

-7.2 指针基本概念

--LinuxCPP0702

-7.3 指针与函数

--LinuxCPP0703

-7.4 指针与复合数据类型(一)

--LinuxCPP0704

-7.5 指针与复合数据类型(二)

--LinuxCPP0705

-7.6 字符串

--LinuxCPP0706

-7.7 动态存储管理(一)

--LinuxCPP0707

-7.8 动态存储管理(二)

--LinuxCPP0708

-7.9 引用

--LinuxCPP0709

-7.10 编程实践

--LinuxCPP0710

-第七讲 指针与引用--编程实践提交入口

第八讲 链表与程序抽象

-8.1 提纲

--LinuxCPP0801

-8.2 数据抽象(一)

--LinuxCPP0802

-8.3 数据抽象(二)

--LinuxCPP0803

-8.4 链表(一)

--LinuxCPP0804

-8.5 链表(二)

--LinuxCPP0805

-8.6 链表(三)

--LinuxCPP0806

-8.7 链表(四)

--LinuxCPP0807

-8.8 函数指针(一)

--LinuxCPP0808

-8.9 函数指针(二)

--LinuxCPP0809

-8.10 抽象链表(一)

--LinuxCPP0810

-8.11 抽象链表(二)

--LinuxCPP0811

-8.12 编程实践

--LinuxCPP0812

-第八讲 链表与程序抽象--编程实践提交入口

第九讲 类与对象

-9.1 提纲

--LinuxCPP0901

-9.2 程序抽象与面向对象

--LinuxCPP0902

-9.3 类类型

--LinuxCPP0903

-9.4 对象(一)

--LinuxCPP0904

-9.5 对象(二)

--LinuxCPP0905

-9.6 类与对象的成员(一)

--LinuxCPP0906

-9.7 类与对象的成员(二)

--LinuxCPP0907

-9.8 类与对象的成员(三)

--LinuxCPP0908

-9.9 继承(一)

--LinuxCPP0909

-9.10 继承(二)

--LinuxCPP0910

-9.11 继承(三)

--LinuxCPP0911

-9.12 多态(一)

--LinuxCPP0912

-9.13 多态(二)

--LinuxCPP0913

-9.14 编程实践

--LinuxCPP0914

-第九讲 类与对象--编程实践提交入口

第十讲 操作符重载

-10.1 提纲

--LinuxCPP1001

-10.2 四则运算符重载(一)

--LinuxCPP1002

-10.3 四则运算符重载(二)

--LinuxCPP1003

-10.4 关系与下标操作符重载

--LinuxCPP1004

-10.5 赋值操作符重载(一)

--LinuxCPP1005

-10.6 赋值操作符重载(二)

--LinuxCPP1006

-10.7 赋值操作符重载(三)

--LinuxCPP1007

-10.8 赋值操作符重载(四)

--LinuxCPP1008

-10.9 赋值操作符重载(五)

--LinuxCPP1009

-10.10 流操作符重载(一)

--LinuxCPP1010

-10.11 流操作符重载(二)

--LinuxCPP1011

-10.12 流操作符重载(三)

--LinuxCPP1012

-10.13 操作符重载总结

--LinuxCPP1013

-10.14 编程实践

--LinuxCPP1014

-第十讲 操作符重载--编程实践提交入口

第十一讲 泛型编程

-11.1 提纲

--LinuxCPP1101

-11.2 泛型编程概览

--LinuxCPP1102

-11.3 异常处理机制(一)

--LinuxCPP1103

-11.4 异常处理机制(二)

--LinuxCPP1104

-11.5 运行期型式信息(一)

--LinuxCPP1105

-11.6 运行期型式信息(二)

--LinuxCPP1106

-11.7 模板与型式参数化

--LinuxCPP1107

-11.8 题外话:术语翻译

--LinuxCPP1108

-11.9 泛型编程实践(一)

--LinuxCPP1109

-11.10 泛型编程实践(二)

--LinuxCPP1110

-11.11 泛型编程实践(三)

--LinuxCPP1111

-11.12 泛型编程实践(四)

--LinuxCPP1112

-11.13 泛型编程实践(五)

--LinuxCPP1113

-11.14 泛型编程实践(六)

--LinuxCPP1114

-11.15 泛型编程实践(七)

--LinuxCPP1115

-11.16 泛型编程实践(八)

--LinuxCPP1116

-11.17 泛型编程实践(九)

--LinuxCPP1117

-11.18 泛型编程实践(十)

--LinuxCPP1118

-11.19 编程实践

--LinuxCPP1119

-第十一讲 泛型编程--编程实践提交入口

第十二讲 Linux系统编程基础

-12.1 提纲

--LinuxCPP1201

-12.2 程序执行环境(一)

--LinuxCPP1202

-12.3 程序执行环境(二)

--LinuxCPP1203

-12.4 程序执行环境(三)

--LinuxCPP1204

-12.5 程序执行环境(四)

--LinuxCPP1205

-12.6 输入输出(一)

--LinuxCPP1206

-12.7 输入输出(二)

--LinuxCPP1207

-12.8 文件系统

--LinuxCPP1208

-12.9 设备

--LinuxCPP1209

-12.10 库(一)

--LinuxCPP1210

-12.11 库(二)

--LinuxCPP1211

-12.12 makefile文件(一)

--LinuxCPP1212

-12.13 makefile文件(二)

--LinuxCPP1213

-12.14 makefile文件(三)

--LinuxCPP1214

-12.15 编程实践

--LinuxCPP1215

-第十二讲 Linux系统编程基础--编程实践提交入口

第十三讲 进程编程

-13.01 提纲

--LinuxCPP1301

-13.02 进程基本概念

--LinuxCPP1302

-13.03 信号

--LinuxCPP1303

-13.04 进程管理(一)

--LinuxCPP1304

-13.05 进程管理(二)

--LinuxCPP1305

-13.06 进程管理(三)

--LinuxCPP1306

-13.07 进程间通信(一)

--LinuxCPP1307

-13.08 进程间通信(二)

--LinuxCPP1308

-13.09 进程间通信(三)

--LinuxCPP1309

-13.10 进程间通信(四)

--LinuxCPP1310

-13.11 进程池

--LinuxCPP1311

-13.12 编程实践

--LinuxCPP1312

-第十三讲 进程编程--编程实践提交入口

第十四讲 线程编程

-14.1 提纲

--LinuxCPP1401

-14.2 线程基本概念

--LinuxCPP1402

-14.3 线程管理(一)

--LinuxCPP1403

-14.4 线程管理(二)

--LinuxCPP1404

-14.5 线程管理(三)

--LinuxCPP1405

-14.6 线程管理(四)

--LinuxCPP1406

-14.7 线程同步机制(一)

--LinuxCPP1407

-14.8 线程同步机制(二)

--LinuxCPP1408

-14.9 C++11线程库(一)

--LinuxCPP1409

-14.10 C++11线程库(二)

--LinuxCPP1410

-14.11 C++11线程库(三)

--LinuxCPP1411

-14.12 C++11线程库(四)

--LinuxCPP1412

-14.13 C++11线程库(五)

--LinuxCPP1413

-14.14 编程实践

--LinuxCPP1414

-第十四讲 线程编程--编程实践提交入口

第十五讲 网络编程

-15.1 提纲

--LinuxCPP1501

-15.2 Internet网络协议

--LinuxCPP1502

-15.3 套接字(一)

--LinuxCPP1503

-15.4 套接字(二)

--LinuxCPP1504

-15.5 编程实践

--LinuxCPP1505

-第十五讲 网络编程--编程实践提交入口

课程文档

-课程PDF文件

LinuxCPP1412笔记与讨论

也许你还感兴趣的课程:

© 柠檬大学-慕课导航 课程版权归原始院校所有,
本网站仅通过互联网进行慕课课程索引,不提供在线课程学习和视频,请同学们点击报名到课程提供网站进行学习。