生成器配合yield实现单线程协作式任务调度,任务为yield暂停的生成器函数,调度器轮询驱动next()执行,支持数据传递与异步I/O模拟。

生成器配合 yield 实现任务调度器,核心在于把每个任务写成可暂停、可恢复的函数,再由一个调度器统一控制它们的执行节奏。它不依赖线程或进程,而是在单线程中通过协作式切换模拟“多任务并发”,适用于 I/O 等待、计算分片、流式处理等场景。
任务必须是生成器函数
每个待调度的任务需定义为生成器函数(Python 中用 def + yield,JS 中用 function*)。yield 就是任务的“让出点”——执行到这里就暂停,把控制权交还给调度器。
- Python 示例:
def task_a():<br> for i in range(3):<br> print(f"A-{i}")<br> yield # 暂停,等待下一次被唤醒 - JavaScript 示例:
function* taskB() {<br> for (let j = 0; j < 2; j++) {<br> console.log(`B-${j}`);<br> yield;<br> }<br>}
调度器负责轮转与驱动
调度器本身不是生成器,而是一个普通函数或类,它维护一组任务的迭代器(即生成器对象),并按策略依次调用它们的 next()(Python/JS 通用)或 send()(支持传参)。
- 每次调用
next(),对应任务从上次yield处恢复,运行到下一个yield或结束; - 若任务返回
{ done: true }(JS)或抛出StopIteration(Python),说明已完成,可从队列中移除; - 简单轮询即可实现公平调度,也可加入优先级、超时、依赖判断等逻辑增强实用性。
yield 可承载数据与控制信号
yield 不只是暂停开关,还能双向传递信息:外部可通过 next(value) 向任务内部注入数据,任务也可用 yield expr 向外输出状态或请求。
- 例如任务在等待数据库响应时
yield "fetch_user_123",调度器捕获该指令后发起异步请求,等结果回来再用next(result)把数据送进任务继续执行; - 这种模式天然适配异步 I/O,是
async/await的底层思想原型。
注意状态隔离与错误处理
每个生成器实例独立保存自己的局部变量、执行位置和堆栈状态,互不干扰。但调度器需主动捕获异常:
- 任务内部抛错时,
next()调用会传播异常,调度器应捕获并决定是否终止该任务或整体退出; - 避免在生成器中做长时间同步阻塞操作(如
time.sleep()或密集循环),否则会卡住整个调度器; - 任务间共享资源(如全局计数器)需加锁或设计为无状态,防止竞态。

















