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

Executor 与 Future、await 关系浅析

Executor 可以想象成 Future 的调度器吗?

是的,非常准确。

Executor(执行器)就是负责管理和轮询(poll)Future 的调度系统

它维护一个就绪任务队列,当一个 Future 返回 Poll::Pending 时,它会注册一个唤醒器(Waker),然后当该 Future 就绪(如 IO 完成)时,Waker 会通知 Executor,Executor 会将其重新放入队列并再次 poll。

Executor 与 Future 的关系

角色职责
Future定义了异步计算的状态机,有一个poll方法,由 Executor 调用。它本身是惰性的,不执行任何操作,除非被 poll。
Executor驱动 Future 运行的外部引擎。它负责:1. 在合适的时机调用Future::poll2. 处理 Waker 通知 3. 管理任务的生命周期(如多线程调度)

关系总结:Future 是被动的“计算任务”,Executor 是主动的“任务驱动器”。两者通过 Waker 进行协作。

Executor 与await是否功能重合?

不重合,它们处于完全不同的层次。

概念层面作用
await语法糖(语言特性).await点挂起当前任务,将控制权交还给 Executor,并等待 Future 完成。它不调度任务,只负责“等待”。
Executor运行时组件(库提供)实际调度和执行 Future,管理线程池或事件循环,驱动所有异步任务向前推进。

类比:Executor 是“发动机”,Future 是“变速器”,而await是“离合器”——它让发动机和变速器暂时分离,但不负责驱动车辆。

详细示例(带计算过程的异步操作)

模拟“费时计算 + 网络请求”来展示这三者的协作。

usetokio::time::{sleep,Duration};usestd::future::Future;usestd::pin::Pin;usestd::task::{Context,Poll};// 1. 定义一个自定义 Future:模拟耗时计算structComputeFuture{count:u32,}implFutureforComputeFuture{typeOutput=u32;fnpoll(mutself:Pin<&mutSelf>,cx:&mutContext<'_>)->Poll<Self::Output>{println!("poll: count = {}",self.count);ifself.count>=10{Poll::Ready(self.count)}else{self.count+=1;// 模拟异步等待:注册一个定时器 Wakerletwaker=cx.waker().clone();tokio::spawn(asyncmove{sleep(Duration::from_millis(100)).await;waker.wake();// 通知 executor 再次 poll});Poll::Pending}}}// 2. 一个异步函数,使用 awaitasyncfnasync_compute()->u32{letresult=ComputeFuture{count:0}.await;// 这里挂起,等待完成result*2}// 3. 另一个异步函数,模拟网络请求asyncfnfetch_data()->u32{sleep(Duration::from_millis(50)).await;// 模拟 IO42}#[tokio::main]// tokio 的 executor 在此asyncfnmain(){// 并发执行两个任务let(computed,fetched)=tokio::join!(async_compute(),fetch_data());println!("computed: {}, fetched: {}",computed,fetched);}

执行流程

#[tokio::main]创建了一个 Executor(多线程工作窃取调度器)。

tokio::join!将两个 Future 提交给 Executor,Executor 开始轮询它们。

当轮询async_compute()时,内部ComputeFuturepoll被调用:

  • 如果count < 10,它注册一个 Waker(通过waker.wake()),并返回Poll::Pending
  • 此时,await关键字将当前任务挂起,控制权返回给 Executor。

Executor 发现任务挂起,就去轮询fetch_data(),它同样可能挂起(sleep)。

当定时器触发时,Waker 被调用,Executor 重新将ComputeFuture放入队列,再次 poll,直到count == 10,返回Poll::Ready

此时await得到结果,继续执行result * 2

所有任务完成,join!返回结果。

三者分工示意(伪代码)

Executor: while 有任务: 选择一个任务 调用 Future::poll(task) 如果返回 Poll::Pending: 保存任务,等待 Waker 否则: 完成并返回结果 Future::poll: 执行一步计算 如果未完成: 注册 Waker 返回 Poll::Pending 否则: 返回 Poll::Ready(value) await: 调用 Future::poll 如果返回 Poll::Pending: 挂起当前 async 函数,保存栈状态 将控制权交还给 Executor 否则: 获取值并继续执行

总结

概念角色是否驱动执行?是否触发调度?
Future状态机否(被动被 poll)
Executor调度器是(驱动 poll)是(管理任务队列)
await等待语法否(只是挂起)否(只是让出控制权)

关键点:await 并不调度任务,它只是将控制权交还给 Executor,让 Executor 去调度其他任务。真正的调度和并发执行完全由 Executor 负责。

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

相关文章:

  • Adam优化器原理与实践:深度学习中的自适应学习率技术
  • FPGA程序,跨时钟打拍的原因
  • PLM系统怎么选:高端装备制造企业选型指南
  • MediaPipe与Unity3D手部追踪实战:从环境搭建到3D渲染全流程
  • 基于YOLOv8的车牌检测系统开发实战
  • 2026年7月保温生日蛋糕袋/烘焙蛋糕袋行业公司推荐_温州市昊玺包装科技有限公司 - 行业平台推荐
  • DeepSeek智能体开发指南:从环境配置到生产部署
  • 亨得利青岛沧口店专业钟表维修保养服务权威公示(2026年7月最新) - 亨得利官方
  • RS-232/485与LVDS/M-LVDS:工业通信与高速接口选型实战指南
  • 自动化发现框架选型指南:从LLM到Agent的工程实践
  • AI学术写作工具:提升论文效率与规范性的关键技术
  • AIGC多厂商集成开发实战指南
  • FPGA工程Git常用操作手册
  • eBPF技术解析:从内核探针到全能观测平台
  • LabVIEW与Halcon结合的工业视觉语义分割实践
  • 见客户前慌慌张张做功课的你,其实可以有个提前踩点的帮手
  • 微信客服自动化:基于大语言模型的AI Agent实践
  • TUSB3410寄存器与DMA配置实战:实现高效USB转串口数据传输
  • 2026模板小程序开发平台推荐来啦!中小企业快上车!
  • 【免费生图】Qwen Image 3.0 Pro 限期免费接入指南:配额限制详解与 429 错误处理方案
  • AI生成评论识别与应对:技术社区的内容真实性挑战
  • 帝舵售后服务中心电话和网点地址实地考察报告多信源验证(2026年7月更新) - 帝舵中国官方服务中心
  • 基于ADS7851EVM-PDK的高性能ADC评估平台实战指南
  • 真力时天津2026年7月最新售后网点地址与全国统一服务热线公告 - 亨得利钟表维修中心
  • 吃透评审3句致命评语,再也不怕本子被刷
  • Redenta:浏览器端PDF文档真正文本删除技术详解
  • 2026年7月最新青岛城阳区流亭街道亨得利钟表服务中心电话公示 - 亨得利官方博客
  • 数据中心备用发电机转主供电源的挑战与解决方案
  • 2026威远系统窗推荐榜:内江米典安装团队覆盖威远全域 - 家居装修资讯
  • TUSB926x固件烧录实战:从SPI Flash到USB桥接的完整指南