突然简书就不支持使用markdown语法自己编辑了,而是和word一样自己选择要样式化的文本,实在是令人很不习惯,准备搭建一个Github主页算了。
使用协程的一个典型例子是生产者消费者模型。我感慨道,果然什么语言不重要啊,思想都是一致的,想起LabVIEW当时用这个生产者消费者用的顺风顺水,因为实在是太好用了,当时编写的每一个系统都尝试使用生产者消费者,特别是与用户交互的界面中,用这个模型简直极大的优化用户的点击体验。当时是使用队列来实现状态的转移,从生产者转移到消费者循环里面进行处理。
今天使用Python来实现一个简单的生产者消费者模型,主要是为了学习协程这个东西,因为Python其实是不支持多线程并行运算,它的多线程其实也是串行的。协程是协作式调度,大概就是一种可控制的回调,使用yield来实现。
主要思想就是用yield来暂停当前的程序或者循环,然后转而执行另外一个,再在恰当的时候回来执行。其实本质上和LabVIEW的生产者消费者有所不同,因为LabVIEW中是支持多线程的,所以生产者消费者是处于两个线程来执行的两个循环,因此才使用了队列数据结构来转移状态。
下面是一个简单的生产者消费者模型:
def consumer():
n = 0
print("consumer init")
while True:
#在这里将函数暂停掉,直到另外地方对函数进行迭代,如producer函数
n = yield n
if not n:
return
n -= 1
print("consume 1, remain %d" %n)
def producer(c):
n = 0
next(c)
while n < 6:
n += 2
print("produce 2, total %d " %n)
#send给generator的value会成为当前yield的结果 并且send的返回结果是下一个yield的结果
#也就是这里send了2,那边n的值就是2,然后减一,然后直到再运行到yield时候,这里返回的是1
n = c.send(n)
print("remain %d"%n)
c.close()
c = consumer()
producer(c)```
producer和consumer协同合作,在一个线程中运行,不需要锁,所以就不会出现死锁。
另外使用协程也可以来定义一个可以访问其他环境的回调函数
首先定义一个回调函数
def apply_async(func,args,,callback):
#callback是一个强制关键字参数
result = func(*args)
callback(result)
def add(x,y):
return x + y
这个回调函数其实就类似于一个消费者
def make_handler():
sequence = 0
while True:
#产生中断
result = yield
sequence += 1
print("[{}] Got : {}".format(sequence,result))
handler = make_handler()
启动生成器
next(handler)
apply_async(add,(2,3),callback=handler.send)
apply_async(add,("hello ","world"),callback=handler.send)```