Python中的协程建立
- 进程在创建时, 需要耗费时间和资源,
- 线程在创建时, 需要耗费时间和资源,
- 协程运行过程中始终只有一个线程,协程也称微线程。
协程优势:
- 有较高的执行效率, 始终只有一个线程, 不存在创建线程和销毁线程需要的时间;
也没有线程切换的开销, 任务需要开启线程数越多, 协程的优势越明显; - 不需要多线程的锁机制
一.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'
if __name__ == '__main__':
# 查看当
print(threading.active_count())
c = consumer()
producer(c)
print(threading.active_count())
二.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()
三.协程与线程的对比
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)