C++异步编程
关键词
std::async、std::paclaged_task、std::promise、std::future
知识点
#include <QCoreApplication>
#include <thread>
#include <mutex>
#include <future>
#include <QDebug>
#include <QThread>
#include <tuple>
/**关于std::future的说明:
** future-期值,用来存储并发编程中的结果,也可以当做传参。
**常用的方法有:std::future::get(),
**std::future与std::shared_future,前者的get方法仅有一次有效,一次后无效而std::shared_future可以多次get()
**除了std::future::get()和`std::future::wait()会阻塞线程,std::future的临时对象在调用`析构函数`时同样会阻塞当前线程。
**注意在局部区域内的`std::future`的析构。
*/
//测试STL中的并发编程
int FunAsync(){
qDebug()<<"async!"<<QThread::currentThread();
return 1;
}
int FunPackaged_task(){
qDebug()<<"packaged_task!"<<QThread::currentThread();
return 2;
}
void FunPromise(std::promise<std::tuple<int,double,uchar>>&& cd_){
qDebug()<<"promise of 1!"<<QThread::currentThread();
cd_.set_value(std::tuple<int,double,uchar>{1,2,3});
}
void FunPromise2(std::future<int>&& _future){
qDebug()<<"promise of 2!"<<QThread::currentThread();
qDebug()<<_future.get();
}
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
//!async
std::future<int> future_async =//async会立即运行,运行结果存在返回的future中,std::launch::async用于强制开启多线程
std::async(std::launch::async,std::move(FunAsync)); //返回结果存储在future中
qDebug()<<future_async.get(); //结果可以用std::future::get得到
//!packaged_task,本身不具有跨线程能力,需配合thread使用
std::packaged_task<int()> pack_task(std::move(FunPackaged_task));
std::future<int> packaged_task_result = pack_task.get_future(); //定义在那里获取结果,这步需要再运行前定义运行却是异步
std::thread thread_packaged_task(std::move(pack_task)); //std::thread线程创建后就会立即执行
qDebug()<<packaged_task_result.get();
thread_packaged_task.join(); //std::thread请确保是join还是detach的结束方式,这是必须的!
//!promise #1,函数接收promise类型的传参,好处:直接执行并返回结果
std::promise<std::tuple<int,double,uchar>> primise_data; //用于线程穿梭的promise变量
std::future<std::tuple<int,double,uchar>> primise_future = primise_data.get_future(); //定义结果返回于那个期值
std::thread thread_promise(FunPromise,std::move(primise_data)); //线程直接执行
std::tuple<int,double,uchar> promise_tem_res = primise_future.get(); //promise::get获取期值数据
qDebug()<<"a:"<<std::get<0>(promise_tem_res)<<"b:"<<std::get<1>(promise_tem_res)<<"c:"<<std::get<2>(promise_tem_res);
thread_promise.join(); //...
//!#2,函数接收future,在主线程中调用,promise::set_value时才会在子线程中处理结果
std::promise<int> future_promise_of_2;
std::thread thread_promise2(FunPromise2,future_promise_of_2.get_future());
future_promise_of_2.set_value(200);
thread_promise2.join();
return a.exec();
}
补充说明
//std::async
//a).当调用`std::future::get()`会阻塞当前线程,直到得到结果。
//b).当调用`std::async(fun*)`时,未必会在新的线程中执行,若明确要在新线程中执行,可以使用`std::launch::async`参数如:`
// std::async(std::launch::async, func*)`;强制在新线程中执行。
//定义函数`
auto fun = [](int value) {
std::this_thread::sleep_for(std::chrono::seconds(5)); //睡眠5s后返回结果`
return 100 + value;
};
//创建仿函数(包装函数)
std::packaged_task<int(int)> pk_task{fun};
//定义仿函数返回值返回于何处
std::future<int> f = pk_task.get_future();
//配合线程正式调用,使用move来实现右值引用,后面跟``着需要的传参`
std::thread t1(std::move(pk_task), 20);
1、packaged_task
可以认为是 仿函数,调用方式有两种:
//1、显式调用(直接调用),如上定义了`pk_task`伪函数,则可以:`pk_task(10)`进行直接调用,而后使用`std::future::get()`得到期值。
//2).异步调用,如a)中一样,通过移动语句把`pk_task(10)`的控制权交给新线程,并开始执行,但别忘了,线程需要`join`或`detach`,否则系统异常终止。
//注意:执行`pk_task`等价于执行`fun(10)`
本文来自博客园,作者:Labant,转载请注明原文链接:https://www.cnblogs.com/lvshen/p/17869098.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具