1.协程
协程与子例程一样,协程(coroutine)也是一种程序组件。相对子例程而言,协程更为一般和灵活,但在实践中使用没有子例程那样广泛。协程源自 Simula 和 Modula-2 语言,但也有其他语言支持。协程不是进程或线程,其执行过程更类似于子例程,或者说不带返回值的函数调用。
一个程序可以包含多个协程,可以对比与一个进程包含多个线程,因而下面我们来比较协程和线程。我们知道多个线程相对独立,有自己的上下文,切换受系统控制;而协程也相对独立,有自己的上下文,但是其切换由自己控制,由当前协程切换到其他协程由当前协程来控制。
2.yield实现协程
import threading
import time
def producer(c):
c.__next__()
n = 0
while n < 5:
n += 1
print("[生产者]生产数据: %s" %(n))
res = c.send(n)
print("[消费者的返回值为:%s" %(res))
def consumer():
r = 'a'
while True:
# yield r ====> r如何获取? print(c.__next__())
# n = yield r ==> c.send("任务1") ===> n = "任务1"
n = yield r
if not n:
return
print("[消费者]运行%s....." %(n))
time.sleep(1)
r = '200 OK'
# # 函数中有yield, 返回值为生成器;
# c = consumer()
# #
# print(c.__next__())
# print(c.send("任务1"))
if __name__ == '__main__':
# 查看当
print(threading.active_count())
c = consumer()
producer(c)
print(threading.active_count())
3.gevent协程实现
import time
from gevent import monkey
monkey.patch_all()
import gevent
def job(n):
for i in range(n):
print(gevent.getcurrent(), i)
time.sleep(1)
def main1():
# 创建三个协程, 并让该协程执行job任务
# 假设多协程执行的任务, 没有IO操作或者等待, 那么协程间是依次运行, 而不是交替运行;
# 假设多协程执行的任务, IO操作或者等待, 那么协程间是交替运行;
g1 = gevent.spawn(job, 2)
g2 = gevent.spawn(job, 3)
g3 = gevent.spawn(job, 2)
# 等待所有的协程执行结束, 再执行主程序;
# g1.join()
# g2.join()
# g3.join()
gevent.joinall([g1, g2, g3])
print("任务执行结束.....")
main1()
4协程案例
import time
from urllib.request import urlopen
from concurrent.futures import ThreadPoolExecutor
import gevent
# 1. 打补丁
from gevent import monkey
from mytimeit import timeit
monkey.patch_all()
# 2. 确定多协程执行的任务内容;
def load_url(url):
# print("正在处理%s...." %(url))
with urlopen(url) as conn:
data = conn.read()
print("%s网页字节数为%s" %(url, len(data)))
URLS = ['http://httpbin.org', 'http://example.com/']*100
@timeit
def gevent_main():
gevents = [gevent.spawn(load_url, url) for url in URLS]
gevent.joinall(gevents)
@timeit
def thread_main():
with ThreadPoolExecutor(max_workers=100) as f:
f.map(load_url, URLS)
if __name__ == '__main__':
gevent_main()
thread_main()
4.协程案例
import time
from urllib.request import urlopen
from concurrent.futures import ThreadPoolExecutor
import gevent
# 1. 打补丁
from gevent import monkey
from mytimeit import timeit
monkey.patch_all()
# 2. 确定多协程执行的任务内容;
def load_url(url):
# print("正在处理%s...." %(url))
with urlopen(url) as conn:
data = conn.read()
print("%s网页字节数为%s" %(url, len(data)))
URLS = ['http://httpbin.org', 'http://example.com/']*100
@timeit
def gevent_main():
gevents = [gevent.spawn(load_url, url) for url in URLS]
gevent.joinall(gevents)
@timeit
def thread_main():
with ThreadPoolExecutor(max_workers=100) as f:
f.map(load_url, URLS)
if __name__ == '__main__':
gevent_main()
thread_main()