当前位置: 首页 > news >正文

异步线程池

目录

  • 线程异步
  • 异步添加任务函数实现
  • 测试代码

线程异步

线程异步是一种编程范式,用于执行任务或操作而不阻塞主线程或其他线程的执行。这种方法特别适用于需要同时处理多个操作或在后台执行长时间运行的任务的场景。线程异步的核心思想是将耗时的操作与主执行流程分离,使得系统能够基于处理其他任务,而无需等待耗时操作完成。

  • 异步执行:与同步操作不同,异步操作不要求调用者在任务完成之前等待结果。异步操作通常会在后台线程中执行,主线程或其他线程可以继续执行其他任务。
  • 线程:在多线程编程中,异步操作通常通过创建新的线程类实现。新线程会执行异步任务,而主线程则继续进行其他操作。
    在上一节的线程池代码中,如果任务函数有返回值,我们就可以通过线程异步的方式,将子线程也就是工作的线程的返回值,传递给主线程,主线程就可以获取到子线程的返回值,从而实现线程之间的数据传递。核心操作就是修改添加任务函数 addTask

异步添加任务函数实现

#include <thread>
#include <mutex>
#include <condition_variable>
#include <queue>
#include <vector>
#include <functional>
#include <atomic>
#include <map>
#include <future>
using namespace std; //测试环境 为方便创建std命名空间 // 线程池类
class ThreadPool 
{
public:ThreadPool(int min, int max = thread::hardware_concurrency());~ThreadPool();template<typename F, typename... Args>auto addTask(F&& f, Args&&... args) -> future<typename result_of<F(Args...)>::type>;{using returnType = typename reslut_of<F(Args...)>::type;auto task = make_shared<packaged_task<returnType()>>(bind(forward<F>(f), forward<Args>(arg)...));future<returnType> res = task->get_future();{unique_locker<mutex> lock(m_queueMutex);m_tasks.emplace([task]() { (*task)(); });}m_condition.notify_one();return res;}
}

关于上述函数的细节解释:

  • addTask 的细节解释如下:
  • 模板参数 FArg... :
    • F 是一个类型参数,代表任务函数的类型或函数对象的类型。这个函数或函数对象将被传递给addTask函数来执行。
    • Arg... 是一个可变参数模板,代表传递给任务函数的参数类型。这些参数将被传递给addTask函数来执行任务函数。
  • auto 返回类型:
    • 返回类型是 future<typename result_of<F(Args...)>::type>,表示 addTask 函数会返回一个 future 对象,用于异步获取任务的结果。result_of<F(Args...)>::type 用于推断任务函数的返回类型。
    • 通过使用 typename ,我们明确告诉编译 std::result_of<F(Args...)>::type 是一个类型,而不是其他实体(例如静态成员)
  • using returnType :
    • 使用 result_of<F(Args...)>::type 来获取任务函数 F 执行后的返回类型,并将其命名为 returnType
  • make_shared<packaged_task<returnType()>>
    • std::make_shared 是一个模板函数,用于创建并返回一个 std::shared_ptr 对象,他以一种异常安全的方式分配和构造对象。这里 std::make_shared 用于创建一个指向 std::packaged_task 的共享指针。
    • std::package_task 是一个模板类,用于包装一个可调用对象(例如函数或函数对象),并允许异步执行并获取其结果。std::packaged_task 提供了一个 std::future 对象,通过该对象可以获取任务的结果。
    • returnType() 表示 packaged_task 将封装一个返回类型为 returnType 的任务。
  • bind(forward<F>(f), forward<Args>(args)...) :
    • std::bind 是一个标准库函数模板,用于绑定参数到可调用对象上,返回一个新的可调用对象。这里 std::bind 绑定了传入的函数 f 和参数 args... ,生成一个不接受参数的新函数对象。
    • std::forward 是一个模板函数,用于完美转发参数。addTask 函数参数 (F&& f, Args&&... args) 为未定引用类型, std::forward 保留了参数的值类别(左值或右值),以便在绑定时正确传递参数,不会被不必要的拷贝或移动。
  • task->get_future() :
    • get_future 返回一个 future 对象, 这个对象用于获取异步任务的结果。
  • 任务队列:
    • unique_lock<mutex> lock(m_queueMutex) 用于加锁,确保线程安全地将任务加入到任务队列中。
    • m_tasks.emplace([task]() { (*task)(); }); 将任务添加到任务队列中,这里使用了一个 lambda 函数来调用 (*task)(), 即执行封装任务。
  • 通知条件变量:
    • m_condition.notify_one() 用于通知一个等待在条件变量上的线程,有新的任务可以执行。

测试代码

int calc(int a, int b)
{int res = a + b;this_thread::sleep_for(chorno::seconds(2));return res;
}int main()
{ThreadPool pool(2, 24);vector<future<int>> results; // 存储异步任务的结果 future<int> 表示返回值为int的future对象for(int i = 0;i < 10; ++i){results.emplace_back(pool.addtask(calc, i, i * 2));}// 等待打印结果for(auto&& res : results){cout << res.get() << endl;}
}

关于 std::future 类的 get() 方法:

  • 阻塞行为:
    • 当调用 get() 方法时,如果异步操作还没有完成,调用线程会被阻塞,直到异步操作完成并且结果准备好为止。这意味着调用 get() 会暂停线程的执行,直到可以安全地获取到结果。
  • 返回值:
    • 一旦异步操作完成,get() 方法会返回异步操作的结果。返回值的类型与 std::future 对象关联的异步操作的结果类型相同。如果异步操作抛出了异常 get() 方法会重新抛出那个异常。
  • 一次性调用:
    • get() 方法只能调用一次。调用一次后,future 对象会变得无效,如果你尝试在调用 get() 后再次调用 get(),会导致未定义行为。

因此,在上述代码中,我们使用 emplace_backfuture<int> 对象添加到 results 向量中,以便在所有任务完成后,我们可以使用 get() 方法获取每个任务的结果,并打印出来。

http://www.jsqmd.com/news/1201456/

相关文章:

  • 2026父母帮子女找对象平台大盘点 正规相亲服务商优缺点解析 选对平台避坑全攻略 - 产业观察报
  • CANN asc-devkit: Ascend C SIMD数据搬运API
  • CameraKit iOS权限管理详解:自动处理相机和麦克风权限的终极指南
  • 2026杭州精装房全屋木作定制品牌实力榜单|高端改造选购干货指南 - 兔兔不是荼荼
  • Qwen3-Embedding-0.6B-8bit模型详解:8位量化如何提升性能与效率
  • 大数据说话!无锡劳力士欧米茄回收口碑榜单,奢二网雄踞榜首 - 大牌深度测评
  • 自然语言处理实战:从分词到词向量的完整工程化实现
  • ViT在不同数据规模下的表现差异:从小数据集到JFT-300M的缩放规律
  • RAG 增量更新方案:知识库变更后的索引重建最小化策略
  • 重庆热水器维修质量调查:2026年深度分析 - 简单到家
  • 【Springboot毕设全套源码+文档】基于springboot非遗文化传承与推广平台系统的设计与实现(丰富项目+远程调试+讲解+定制)
  • 双职工家庭救星|在悠享美家找到了靠谱育儿嫂 - 资讯纵览
  • 欧米茄无锡授权售后服务中心|恒隆商圈门店 + 售后客服 400-883-8097 权威信息公告(2026年7月最新) - 欧米茄中国售后中心
  • YOLOv8 自定义目标检测训练实战:预训练推理、数据集训练与部署
  • AI核心技术解析与应用实践指南
  • PatchTST时间序列预测完全指南:从零开始掌握Transformer长期预测模型
  • 新手回收黄金怎么避坑?2026上海优选合扬全国奢侈品交易中心正规老店 - 一站式奢品变现
  • Mac 与 iPad 的 AppleCare Plus 订阅费将涨,苹果多产品线提价缓解成本压力
  • 为什么YOLO系列始终坚守CNN路线?Transformer融合架构在YOLO中的真实落地情况
  • 计算机毕业设计之基于jsp英语口语考试系统
  • 终极ModTheSpire指南:轻松为《杀戮尖塔》注入无限可能
  • AndroidFastScroll:终极Android快速滚动库,让RecyclerView滚动速度提升3倍
  • 2026玉林黄金回收交易指南|行业套路拆解与优质门店推荐 - 小路路在天舞
  • 剑河本地装饰设计贵州森林装饰有限公司装修避坑指南 - 百航
  • Jido网络监控:构建高性能分布式监控与告警代理的完整指南
  • 2026 年 7 月 16 日哈尔滨黄金回收价汇总|正规门店大盘报价对比 - 一站式奢品变现
  • Gemma-4-12B-coder-fable5-composer2.5-v1与其他量化模型的对比分析
  • gvt核心功能详解:fetch、restore、update、list、delete命令全解析
  • 2026年婚恋线上平台正规平台大盘点:靠谱婚恋平台筛选避坑指南 - 行业观察网
  • 本地大模型部署:llama.cpp与Ollama实战指南