C++ 多线程编程(三) 获取线程的返回值——future

news2024/11/17 18:29:10

C++11标准库增加了获取线程返回值的方法,头文件为<future>,主要包括futurepromisepackaged_taskasync四个类。

那么,了解一下各个类的构成以及功能。

1 future

future是一个模板类,它是传输线程返回值(也称为共享状态)的媒介,也可以理解为线程返回的结果就安置在future中。

future版本:C++11      头文件<future>
构造函数

1. future() noexcept;

默认构函数,是一个无效future,valid函数返回false.

2. future(future&& other) noexcept

移动构造函数,使用后other.valid()为false。

3. future(const future& other) = delete

禁用拷贝构造函数。

析构函数~future();
get

std::future<T>  T get();

获取共享状态,如果共享状态尚未就绪(比如线程未结束),则堵塞,等效于wait函数。

valid

bool valid() const noexcept;

判断future是否有效。无效future有三种情况:一是使用默认构造函数创建的;调用过移动构造函数;三是调用过get函数

wait

void wait() const;

获取共享状态,如果共享状态尚未就绪(比如线程未结束),则堵塞;阻塞结束之后,还需要继续调用get才能获取共享状态,此时get不再阻塞。

wait_for设置最大阻塞时间
wait_until设置最大阻塞时刻

跟多线程相关的类,大多都有一个特点,就是禁用拷贝构造函数,仅能使用移动构造函数。

单独使用future依然没有办法获取线程的返回值,必须与promise、packaged_task或者async搭配使用。而且,单独创建出来的future对象甚至都没有意义,必须从promise、packaged_task或者async中创建,才有意义。

2 promise

promise对象可以看做是future类的封装,它可以原子的修改future的共享状态。

promiseC++ 11                  头文件: <future>
构造函数

1. promise();

默认构造函数,构造一个共享状态为空的 std::promise

2. promise(promise&& other) noexcept;

移动构造函数,用原属 other 的共享状态构造新的 std::promise 对象,使用移动语义。构造完毕后, other 无共享状态;

3. future(const future& other) = delete;

禁用拷贝构造函数。

get_future

std::future<T> get_future();

获取共享状态,返回一个future对象。

set_value原子地存储 value 到共享状态,并令状态就绪(future::get结束阻塞)。
set_value_at_thread_exit原子地存储 value 到共享状态,而不立即令状态就绪。在当前线程退出时,再令状态就绪。
#include <thread>
#include <future>
#include <iostream>

void fun1(std::promise<int> pro) {
    std::this_thread::sleep_for(std::chrono::seconds(3));
    pro.set_value(100);
    return;
};

int main()
{
    std::promise<int> pro;
    std::future<int> fut = pro.get_future();
    std::thread th(&fun1, std::move(pro));
    th.detach();
    std::cout << fut.get() << std::endl;
}

需要注意的一点是,future的模板类型与线程函数的返回类型无关。上边fun1函数的返回值为void,但是future类型为int。

3 packaged_task

packaged_task是一个类,它主要包含了一个future对象和一个任务,这个任务可以是函数、 lambda 表达式、 bind 表达式或其他函数对象。

packaged_taskC++11                      头文件: <future>
构造函数

template<class F>

explicit packaged_task(F&& f);

f 是一个函数,也就是任务入口。

get_future

std::future<T> get_future();

获取共享状态,返回一个future对象。

()运算符

void operator()(ArgTypes...args);

args 为参数运行存储的任务;任务结束时,将返回值存储于共享状态,并令共享状态就绪。该函数会新开一个线程并以detach模式运行新线程。

#include <iostream>
#include <cmath>
#include <thread>
#include <future>
#include <functional>
 
// 避免对 std::pow 重载集消歧义的独有函数
int f(int x, int y) { return std::pow(x,y); }
 
void task_lambda()
{
    std::packaged_task<int(int,int)> task([](int a, int b) {
        return std::pow(a, b); 
    });
    std::future<int> result = task.get_future();
 
    task(2, 9);
 
    std::cout << "task_lambda:\t" << result.get() << '\n';
}
 
void task_bind()
{
    std::packaged_task<int()> task(std::bind(f, 2, 11));
    std::future<int> result = task.get_future();
 
    task();
 
    std::cout << "task_bind:\t" << result.get() << '\n';
}
 
void task_thread()
{
    std::packaged_task<int(int,int)> task(f);
    std::future<int> result = task.get_future();
 
    std::thread task_td(std::move(task), 2, 10);
    task_td.join();
 
    std::cout << "task_thread:\t" << result.get() << '\n';
}
 
int main()
{
    task_lambda();
    task_bind();
    task_thread();
}

输出:

 与promise不同的是,packaged_task任务的返回类型就是future的类型。

4 async

async是一个模板函数,它综合了前边promise和packaged_task的功能,一个函数就可以实现线程创建、任务执行、获取返回值等功能。

async的返回值是一个future对象,async所执行的任务完成后,会令共享状态进入就绪状态。

#include <thread>
#include <future>
#include <iostream>
#include <unistd.h>

int main()
{
    auto ff = std::async(std::launch::async, []{ sleep(2); return 2.3; }); 

    std::cout << ff.get() << std::endl;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/492941.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

2-Lampiao百个靶机渗透(精写-思路为主)框架漏洞利用2

特别注明&#xff1a;本文章只用于学习交流&#xff0c;不可用来从事违法犯罪活动&#xff0c;如使用者用来从事违法犯罪行为&#xff0c;一切与作者无关。 文章目录 前言一、环境重新部署二、AWVSxray联动和xraybs联动1.安装AWVSxray2.让xray和bs先联动3.AWVS和xray联动 三、p…

【Spring框架全系列】如何创建一个SpringBoot项目

&#x1f307;哈喽&#xff0c;大家好&#xff0c;我是小浪。前几篇博客我们已经介绍了什么是Spring&#xff0c;以及如何创建一个Spring项目&#xff0c;OK&#xff0c;那么单单掌握Spring是完全不够的&#xff0c;Spring的家族体系十分强大&#xff0c;我们还需要深入学习&am…

力扣---LeetCode160. 相交链表(代码详解+流程图)

文章目录 前言160. 相交链表链接&#xff1a;思路&#xff1a;方法一&#xff1a;暴力求解法1.1 时间复杂度&#xff1a;O(M*N)1.2 代码&#xff1a; 方法二&#xff1a;双指针2.1 时间复杂度&#xff1a;O(N)2.2 代码&#xff1a;2. 3流程图&#xff1a; 注意&#xff1a;补充…

13. Transformer(下)

P33 Transformer&#xff08;下&#xff09; 视频链接 P33 Transformer&#xff08;下&#xff09; 1. Decoder: Autoregressive(AT) Decoder原理&#xff1a; Encoder vs Decoder&#xff1a; Masked&#xff1a; how to stop&#xff1a; 2. Decoder: Non-autoregressive(…

网络基础——网络的发展史

作者简介&#xff1a;一名计算机萌新、前来进行学习VUE,让我们一起进步吧。 座右铭&#xff1a;低头赶路&#xff0c;敬事如仪 个人主页&#xff1a;我叫于豆豆吖的主页 目录 前言 一.网络发展史 1. ARPANET 2.TCP/IP协议 3. 互联网 4.Web浏览器 5.搜索引擎 6. 社交网…

如果你访问了某个网站,又不想让人知道怎么办?

问大家一个问题&#xff1a;如果你访问了某个网站&#xff0c;又不想让人知道怎么办&#xff1f; 你可能会说&#xff0c;把浏览器浏览历史记录清除&#xff0c;或者直接用无痕模式。 如果你只能想到这一层&#xff0c;那只能说图young&#xff01; 这么说吧&#xff0c;理论…

操作系统原理 —— 调度的概念、层次(十一)

调度的基本概念 在操作系统中的调度&#xff0c;是指操作系统从就序队列中选择一个作业&#xff0c;或者进程进行执行。 举个例子&#xff1a; 比如我们去银行窗口排队&#xff0c;排队的人就相当于就绪列表&#xff0c;窗口就相当于是操作系统&#xff0c;窗口需要服务排队…

npm的使用和命令

3.0 npm 什么是npm 是node管理包的工具 3.1 初始化包管理描述文件 package.json npm init // 会询问你每次的选项 或 npm init -y // 不询问你选项&#xff0c;默认就是确定 首先建立一个文件在路径里面全选写cmd 然后打开环境 在里面写npm init -y回车 就会在你原来空的文…

编写用户帮助/操作手册指南

背景&#xff1a; 用户操作手册是一份指导用户使用产品或服务的重要手册。 一个新系统&#xff0c;需要写用户操作手册&#xff0c;该从何下笔&#xff1f;本篇是一篇教你编写用户帮助/操作手册的指南&#xff5e; 首先&#xff0c;先来看一个反例 &#xff1a; 这个是我入职…

移动通信(17)预编码

源于某篇学位论文 利用预编码技术可以有效抑制大规模天线传输中的干扰&#xff0c;提高链路的峰值速率。大规模天线技术在提升性能的同时也存在很大的干扰问题。多天线传输中带来的多径干扰不可忽视。通常在接收端抑制干扰算法通常实现起来较为复杂&#xff0c;若采用预编码技…

安装Node.js和cnpm

一、安装Node.js 1.下载 Node.js官网下载 根据自身系统下载对应的安装包&#xff08;我这里为Windows10 64位&#xff0c;故选择下载第一个安装包&#xff09; 2、然后点击安装&#xff0c;选择自己要安装的路径&#xff0c;此处我选择的是&#xff1a;D:\Program Files\node…

中级软件设计师备考---UML

目录 面向对象的基础概念面向对象的设计原则UML的各类图设计模式对比分类 面向对象的基础概念 【只介绍一些我个人不太熟悉的概念】 继承和泛化&#xff1a;泛化和继承可以理解为是一个逆过程&#xff1a;泛化就是有子类抽象出一个父类&#xff0c;而继承就是由父类具体化一个…

程序员崩溃的N个瞬间

说到程序员&#xff0c;在外界眼里&#xff0c;他们是掌控代码的大神&#xff0c;他们是改变世界的王者。其实程序员的工作不容易&#xff0c;不信&#xff0c;就来看看程序员崩溃的各种瞬间—— 01、公司实习生找bug 02、在调试时&#xff0c;将断点设置在错误的位置 03、当我…

eventMesh 本地搭建记录

官方文档: Apache EventMesh (Incubating) | Apache EventMesh (作为整体了解 可以先看看架构) 按照官方文档需要搭建服务 eventmesh-store 文档推荐的是 rocketmq docker pull apache/rocketmq:4.9.4 部署rmq 的过程 1.nameServer docker run -d -p 9876:9876 -v pwd/d…

NECCS|全国大学生英语竞赛C类|词汇和语法|语法题|时态 非谓语动词 |19:00~20:15|完形填空·词性转化

14:35&#xff5e;14:45 15:45&#xff5e;16:2019:00&#xff5e;20:15 http://t.csdn.cn/XbsUy 目录 &#xff08;一&#xff09;时态 7. 将来进行时 8. 过去将来进行时 9. 现在完成时 10. 过去完成时​编辑 11. 将来完成时 12. 现在完成时 13. 过去完成进行时 &#xff08;…

David Silver Lecture 4: Model-Free Prediction

1 Introduction 任务&#xff1a;第三章使用动态规划方法&#xff0c;解决known的MDP问题&#xff0c;这章通过model free prediction对一个unknown的MDP估计他的value function。下一章通过Model free control的方法针对一个unknown的MDP optimise value function。 2 Monte…

密码学【java】初探究加密方式之消息摘要

文章目录 一 消息摘要1.1 消息摘要的特点1.2 消息摘要常见算法1.3 数字摘要的运用举例&#xff1a;1.4 字符串数字摘要演示1.5 其他数字摘要算法演示1.6 获取文件消息摘要 一 消息摘要 消息摘要&#xff08;Message Digest&#xff09;又称为数字摘要(Digital Digest)它是一个…

Feign组件的使用及开发中使用方式

在微服务的服务集群中服务与服务之间需要调用暴露的服务.那么就需要在服务内部发送http请求&#xff0c; 我们可以使用较为老的HttpClient实现&#xff0c;也可以使用SpringCloud提供的RestTemplate类调用对应的方法来发送对应的请求。 说明&#xff1a; 现在有两个微服务一个是…

java反序列化cc3链分析

前言 休息完五一&#xff0c;继续卷&#xff0c;原本想结束cc链的&#xff0c;但是发现cc3链好像用的方法不太一样&#xff0c;感觉也是可以记录下来&#xff0c;这里感觉cc3链有一些像cc1链的变种&#xff0c;就像是给你一些绕过的操作 在说一句&#xff0c;白日梦组长永远的神…

使用开源的zip.cpp和unzip.cpp实现压缩包的创建与解压

目录 1、使用场景 2、压缩包的创建 3、压缩包的解压 4、CloseZipZ和CloseZipU两接口的区别 5、开源zip.cpp和unzip.cpp文件的下载 VC常用功能开发汇总&#xff08;专栏文章列表&#xff0c;欢迎订阅&#xff0c;持续更新...&#xff09;https://blog.csdn.net/chenlycly/…