`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是创建和控制 ...
随机推荐
- js 做树形数组查询筛选功能
对二级菜单进行搜索查询: watch: { librarySearch(val) { if(val == '') { this.libraryFiles = this.libraryFilesAll ...
- Jmeter函数助手5-RandomFromMultipleVars
RandomFromMultipleVars函数用于获取指定变量的随机变量值. Source Variable(s) (use | as separator):传入指定的变量名称,这里的变量可以是单值 ...
- 【POI】Excel数据导入
Postman请求方式: Controller接口代码: /** * /partImport/part/importUpload * @param importFile * @return */ @P ...
- python科学计算:加速库numba —— 安装和试用
安装(anaconda环境下) conda install numba Demo代码: from numba import jit from numpy import arange import nu ...
- 很好用的python游戏环境:强化学习算法走迷宫游戏环境(导航问题 navigation):分享一个python语言的迷宫游戏环境
项目的GitHub地址(作者:莫凡): https://github.com/MorvanZhou/mmaze 运行的示例代码: import mmaze start = (0, 0) end = ( ...
- 【转载】 取消idea双击shift时出现的全局搜索 (使用pycharm IDE时出现的问题)
原文地址: https://blog.csdn.net/hxy199421/article/details/83030603 最近在使用pycharm的时候出现文章标题的问题,由于以前写的代码都是比较 ...
- Ubuntu18.04动态桌面壁纸variety的安装
Ubuntu18.04桌面系统,安装动态更换桌面壁纸的应用,即安装软件 variety. variety 的安装: sudo apt install variety 安装好以后就会自动启动. 我们可以 ...
- Google公司的python编码规范指南
原文地址: https://google.github.io/styleguide/pyguide.html ============================================= ...
- git No url found for submodule path 'xxxxx' in .gitmodules
删除之前的子模块记录 rm -rf git rm --cached 然后加进去 git submodule add
- AI编程助手那些事儿
最近跟身边的程序员老杆子讨论需求时,惊奇的发现,他居然没使用AI编程助手.一时间有2个想法从大脑闪过,然后心里还带了一丝轻蔑: AI编程助手这么好的东西,你居然不用. 作为老程序员,你居然不跟上时代步 ...