`std::packaged_task`、`std::thread` 和 `std::async` 的区别与联系
std::packaged_task、std::thread 和 std::async 的区别与联系
std::packaged_task、std::thread 和 std::async 都是 C++11 中提供的并发工具,用于执行任务并处理多线程操作。虽然它们都有类似的作用(并发执行任务),但在功能和使用方式上有显著区别。下面分别解释它们的特点,并说明它们的区别与联系。
1. std::packaged_task
特点:
- 封装可调用对象:
std::packaged_task能将一个可调用对象(如函数、lambda、函数对象)包装起来,使其能够异步执行。 - 返回结果:与任务关联的
std::future对象可以通过get()方法获取任务的执行结果。 - 任务执行方式:
std::packaged_task本身不负责执行任务,它只是一个包装器,任务的实际执行需要通过线程、std::async或直接调用。
使用场景:
- 适用于你想自己控制任务的执行过程,并且希望能够获得任务的返回值。
std::packaged_task提供了一种灵活的方式来包装任务,然后在不同的线程中执行它。
示例:
std::packaged_task<int(int)> task([](int x) { return x * x; });
std::future<int> result = task.get_future();
// 通过线程执行任务
std::thread t(std::move(task), 10);
t.join();
std::cout << "Result: " << result.get() << std::endl; // 输出: Result: 100
2. std::thread
特点:
- 手动管理线程:
std::thread是最基础的并发工具,用于创建并管理一个线程。你可以将任何可调用对象传递给线程,在线程中并发执行。 - 生命周期管理:线程的生命周期需要手动管理。你需要确保线程完成后调用
join()(等待线程结束)或detach()(分离线程)。 - 不返回结果:
std::thread只负责启动一个新线程,它本身没有机制直接返回线程执行的结果。如果需要返回结果,你需要配合std::future或其他同步机制使用。
使用场景:
- 适用于你希望直接管理线程的创建、执行和结束过程的场景。
std::thread提供了底层的并发控制能力。
示例:
std::thread t([] {
std::cout << "Hello from thread!" << std::endl;
});
t.join(); // 等待线程执行完毕
3. std::async
特点:
- 简化异步任务执行:
std::async用于异步执行任务。它自动管理线程的启动、执行和返回结果。 - 返回结果:
std::async返回一个std::future对象,允许你通过future.get()获取任务执行的结果。 - 可选择异步或同步:
std::async可以选择是否启动一个新线程(std::launch::async)或延迟执行(std::launch::deferred)。 - 自动管理:与
std::thread不同,std::async不需要手动join()或detach(),它会自动管理任务的执行和资源回收。
使用场景:
- 适用于你希望将任务提交给系统自动管理,并且无需手动控制线程的场景。
std::async提供了高层次的异步任务管理功能。
示例:
auto result = std::async([](int x) { return x * x; }, 10);
std::cout << "Result: " << result.get() << std::endl; // 输出: Result: 100
总结区别
| 特性 | std::packaged_task |
std::thread |
std::async |
|---|---|---|---|
| 任务封装 | 通过 packaged_task 包装可调用对象 |
将可调用对象传递给线程直接执行 | 提交任务,系统自动决定如何执行 |
| 返回结果 | 通过 std::future 获取结果 |
不提供直接的返回机制 | 返回 std::future,自动管理任务返回值 |
| 线程管理 | 需要手动启动线程来执行任务 | 需要手动创建、管理、结束线程 | 自动管理任务执行,提供异步和同步模式 |
| 资源管理 | 任务执行和线程生命周期分开管理 | 需要显式 join() 或 detach() 线程 |
自动管理资源,任务结束后自动回收资源 |
| 使用场景 | 灵活包装任务,控制任务执行过程 | 直接管理线程的生命周期和执行 | 简化的异步任务执行方式 |
通俗解释:
std::packaged_task:像打包一个任务的“快递包裹”,让你可以把任务交给别人(例如线程)去执行,然后你可以用“包裹单号”(std::future)去查询结果。std::thread:是“直接开车送快递”,你自己负责启动这个“车”(线程),并且需要决定什么时候让车停下来(join())或让车继续开(detach())。std::async:就像是找个“跑腿服务”,你把任务提交给跑腿系统,它会决定找人去做任务,并且在任务完成后,你可以直接通过“跑腿结果”(std::future)拿到结果。你不需要担心“车子”(线程)的管理。
`std::packaged_task`、`std::thread` 和 `std::async` 的区别与联系的更多相关文章
- C++并发编程之std::async(), std::future, std::promise, std::packaged_task
c++11中增加了线程,使得我们可以非常方便的创建线程,它的基本用法是这样的: void f(int n); std::thread t(f, n + 1); t.join(); 但是线程毕竟是属于比 ...
- c++ 如何获取多线程的返回值?(std::thread ,std::async)
//简单的 c++11 线程,简单方便,成员函数随便调用,非成员函数也一样,如需要获取返回时,请自行使用条件变量 std::thread run([&](){ //执行一些耗时的操作 retu ...
- C++11 并发指南四(<future> 详解二 std::packaged_task 介绍)
上一讲<C++11 并发指南四(<future> 详解一 std::promise 介绍)>主要介绍了 <future> 头文件中的 std::promise 类, ...
- C++11之std::future和std::promise和std::std::packaged_task
为什么C++11引入std::future和std::promise?C++11创建了线程以后,我们不能直接从thread.join()得到结果,必须定义一个变量,在线程执行时,对这个变量赋值,然后执 ...
- C++并发低级接口:std::thread和std::promise
std::thread和std::promise 相比std::async,std::thread就原始多了.thread一定会创建新线程(而不是像async那样创建的时候可能不会,后面才创建新线程( ...
- boost和std中的thread的引用参数
boost 1.60.0 先上代码: #include <boost/thread.hpp> #include <iostream> void add(int &i) ...
- could not deduce template argument for 'const std::_Tree<_Traits> &' from 'const std::string'
VS2008, 写一个简单的demo的时候出现了这个: 1>------ Build started: Project: GetExportTable, Configuration: Relea ...
- std::u32string conversion to/from std::string and std::u16string
I need to convert between UTF-8, UTF-16 and UTF-32 for different API's/modules and since I know have ...
- c++11 标准库函数 std::move 和 完美转发 std::forward
c++11 标准库函数 std::move 和 完美转发 std::forward #define _CRT_SECURE_NO_WARNINGS #include <iostream> ...
- .NET多线程(Thread,ThreadPool,Task,Async与Await)
.NET多线程是什么? 进程与线程 进程是一种正在执行的程序. 线程是程序中的一个执行流. 多线程是指一个程序中可以同时运行多个不同的线程来执行不同的任务. .NET中的线程 Thread是创建和控制 ...
随机推荐
- holiday week3
本周开始进行小学期实验报告B 上周LOL打的rank分又掉了回去 星际争霸打到了铂金段位 JAVA预备在小学期完成之后开始正式学习 现已了解雏形 本周发布了一个视频https://www.bilibi ...
- Nuxt.js必读:轻松掌握运行时配置与 useRuntimeConfig
title: Nuxt.js必读:轻松掌握运行时配置与 useRuntimeConfig date: 2024/7/29 updated: 2024/7/29 author: cmdragon exc ...
- 【Java】Input,Output,Stream I/O流 03 系统标准流 & 打印流
Standard Input,Output Stream 标准输入输出流 - System.in 系统标准输入流 所属InputStream Scanner(System.in); 默认从键盘获取输入 ...
- 制作Linux系统的启动盘
我不是没有试过软碟通制作启动盘 在写入U盘的选项确认的时候,盘区不支持NTFS!? 另外什么大白菜和老毛桃这样的根本就不支持Linux镜像加载 还是百度的这个靠谱 https://jingyan.ba ...
- 【ECharts】01 快速上手
简单介绍: ECharts 是一个使用 JavaScript 实现的开源可视化库,涵盖各行业图表,满足各种需求. ECharts 遵循 Apache-2.0 开源协议,免费商用. ECharts 兼容 ...
- 灵巧度最高的机械手 —— Clone公司
地址: https://www.youtube.com/watch?v=ikrDqfnZNLU Clone 公司: 生产通过液压驱动的仿生机器人.
- 2024年 智能机器人元年 —— 国内的智能机器人(humanoid)公司当下最大的压力(最为急迫的任务)是什么?
可以说,2024年是人形机器人的元年.我国在去年年底将发展智能机器人立为了第一线的重要科技发展方向,并计划在2024年.2025年建立出完整的产业链条,并培育出几家成熟的行业领先的智能机器人公司.而我 ...
- 深度学习框架theano下的batch_norm实现代码——强化学习框架rllab
深度学习框架theano下的batch_norm实现代码--强化学习框架rllab # encoding: utf-8 import lasagne.layers as L import lasagn ...
- 【转载】 TensorFlow - 框架实现中的三种 Graph图结构
原文地址: https://zhuanlan.zhihu.com/p/31308381 -------------------------------------------------------- ...
- fastDFS安装时,./make.sh编译时出错找不到./make.sh: line 99: perl: command not found
1.背景 报错如下: 2.解决方案 执行命令: yum -y install zlib zlib-devel pcre pcre-devel gcc gcc-c++ openssl openssl-d ...