Python 使用生成器实现并发:协程与任务调度

1 下载量 16 浏览量 更新于2024-08-30 收藏 88KB PDF 举报
"本文讨论了如何使用Python中的生成器(协程)来替代系统线程进行并发处理,这种方法也称为用户级线程或绿色线程。通过深入理解生成器函数和`yield`语句,我们可以创建自定义的任务调度器来管理并发任务的执行流程。" 在Python中,生成器是一种特殊类型的迭代器,它允许你在函数内部使用`yield`语句,而不是返回一个值。当`yield`语句被执行时,函数的状态会被保存,包括所有局部变量,这使得函数可以在稍后的时间点从暂停的地方继续执行,而无需重新初始化。 在并发处理场景下,生成器可以作为轻量级的任务单元,它们不会像线程那样涉及系统级别的上下文切换,因此更节省资源。通过编写调度器,我们可以控制生成器的执行顺序,实现类似多线程的并发效果,但避免了线程同步的复杂性和开销。 例如,给出的`countdown`和`countup`生成器函数分别实现了倒计时和递增计数的功能。它们通过`yield`语句暂停自身执行,等待被调度器重新激活。 ```python def countdown(n): while n > 0: print('T-minus', n) yield n -= 1 print('Blastoff!') def countup(n): x = 0 while x < n: print('Counting up', x) yield x += 1 ``` `TaskScheduler`类是实现任务调度的核心,它维护了一个双端队列 `_task_queue` 来存储待执行的任务(即生成器)。`new_task` 方法用于添加新的任务到队列,`run` 方法则负责执行这些任务,直到队列为空。在执行过程中,`run` 方法会取出队列头部的任务,调用 `next(task)` 运行生成器直至遇到 `yield`,然后将其再次放回队列,以便后续执行。如果生成器结束(`StopIteration` 异常),则从队列中移除。 ```python class TaskScheduler: def __init__(self): self._task_queue = deque() def new_task(self, task): self._task_queue.append(task) def run(self): while self._task_queue: task = self._task_queue.popleft() try: next(task) self._task_queue.append(task) except StopIteration: pass # 示例用法 sched = TaskScheduler() sched.new_task(countdown(10)) sched.new_task(countdown(5)) sched.new_task(countup(15)) sched.run() ``` 在上述示例中,`countdown` 和 `countup` 生成器被添加到调度器中,并在 `run` 方法中按顺序执行。这展示了如何使用生成器和自定义调度器来实现并发执行,且无需依赖线程或其他并发库。 总结来说,Python 的生成器提供了一种高效、轻量级的方式来实现并发处理。通过结合`yield`语句和自定义调度器,我们可以构建出用户级线程模型,有效地管理多个任务,实现程序的并发执行。这种方式特别适合于那些计算密集型或I/O密集型但不需要大量系统资源的任务,以及对于性能和内存占用有较高要求的场景。