`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是创建和控制 ...
随机推荐
- vue中的<script setup>与<script>
<script setup>是在vue3.2之后新增的语法糖,简化了API的写法 1.声明的变量无需return,可以直接在模板中使用,实现了顶层的绑定 2.引入组件会自动注册,无需再使用 ...
- 打开电脑属性 设置 windows
组合键:win+R,输入sysdm.cpl,然后运行. 右键"此电脑",选择属性,然后点击高级系统设置. 组合键:win+Pause/Break. 在命令提示符中输入SystemP ...
- SpringBoot整合knife4j(swagger)
关于knife4j Knife4j是一个基于Swagger的Java接口文档生成工具,它提供了一套可视化的界面来展示和测试API接口.Knife4j通过解析接口代码中的Swagger注解,自动生成接口 ...
- 14、SpringMVC之注解配置
14.1.概述 在实际工作中,一般使用配置类和注解代替web.xml和SpringMVC配置文件的功能: 在 Servlet3.0 环境中,容器会在类路径中查找实现了 javax.servlet.Se ...
- 国内的开源AI模型共享网站(AI模型的GitHub)—— modeldscope —— 对标外网的“huggingface”,modelscope好用吗?
搞AI的应该都是知道huggingface是啥的,这里不过多介绍,简单的来说就是AI模型的Github,之所以这么说是因为计算机的项目往往都是代码文件,所有计算机项目的Github只需要上传项目的代码 ...
- IPython notebook(Jupyter notebook)指定IP和端口运行
1. 使用conda 安装 jupyter conda install jupyter 2. 在服务器端不打开浏览器,指定 端口, IP , 运行jupyter notebook 这里假设端口 ...
- Ubuntu22.04系统安装DeepMind Lab
相关资料: DeepMind Lab的一些python例子-----(Ubuntu22.04系统安装DeepMind Lab)后续 ================================== ...
- Ubuntu系统:NVIDIA显卡关闭图形显示 —— 彻底禁用NVIDIA GPU 的显示输出接口 —— ubuntu无桌面方式启动 —— NVIDIA显卡模式切换(显示模式切换为计算模式)
相关: ubuntu desktop改用无桌面方式启动 在使用Linux做异构计算等科学计算的时候一个常见的问题就是: NVIDIA显卡关闭图形显示 -- 彻底禁用NVIDIA GPU 的显示输出接口 ...
- Linux嵌入式所有知识点-思维导图-【一口君吐血奉献】
一.前言 很多粉丝问我,我的Linux和嵌入式当初是如何学习的? 其实彭老师在最初学习的过程中,走了相当多的弯路: 有些可以不学的花了太多的时间去啃 有些作为基础必须优先学习的,却忽略了, 结果工作中 ...
- 12米空间分辨率DEM数据申请下载:TanDEM-X数据集
本文介绍全球12米与30米高空间分辨率的数字高程模型(DEM)数据--TanDEM-X数据的下载申请方法. Tandem-X卫星项目于2010年6月启动,并于2010年6月21日和2010年1 ...