協程
概念 :
是單線程下的併發,又稱微線程,纖程。英文名Coroutine。
簡單的解釋:協程是一種用戶態的輕量級線程,即協程是由用戶程序自己控制調度的。
優點 :
- 協程的切換開銷更小,屬於程序級別的切換,操作系統完全感知不到,因而更加輕量級
- 單線程內就可以實現併發的效果,最大限度地利用CPU、
缺點 :
- 協程的本質是單線程下,無法利用多核,可以是一個程序開啓多個進程,每個進程內開啓多個線程,每個線程內開啓協程
- 協程指的是單個線程,因而一旦協程出現阻塞,將會阻塞整個線程
特點 :
必須在只有一個單線程裏實現併發修改共享數據不需加鎖用戶程序裏自己保存多個控制流的上下文棧。
yield的實現
代碼演示:
import time
def consumer(name):
"""
這是一個生成器,調用的時候才執行
:param name: 消費者的名字
:return: 包子
"""
print("消費者準備吃包子。。。。。")
while True:
new_baozi = yield #接受調用生成器的值
print("%s吃第%d個包子"%(name,new_baozi))
time.sleep(1)
def producer(name):
r = con1.__next__()
r = con2.__next__()
count = 1
while True:
print("%s正在生產第%d個包子和第%d個包子"%(name,count,count+1))
#調用生成器併發送數據
con1.send(count)
con2.send(count+1)
count += 2
if __name__ == '__main__':
con1 = consumer("鐺鐺")
con2 = consumer("煤球")
p = producer("孫大廚")
運行結果:
greenlet模塊
greenlet是一個用C實現的協程模塊,相比與python自帶的yield,它可以使你在任意函數之 間隨意切換,而不需要把這個函數先聲明爲generator
安裝 :pip3 install greenlet。如果引入的時候還是報錯,使用pycharm進行下載安裝, 選擇 file --> settings --> Project:項目名稱 --> Project Interpreter–>…
代碼演示:
from greenlet import greenlet
def work1():
print(12)
# 3.切換到test2()函數中
gr2.switch()
def work2():
print(20)
gr1.switch()
print(43)
#1. 將要執行的函數封裝到 greenlet 對象中
gr1 = greenlet(work1)
gr2 = greenlet(work2)
#2.想先執行哪個函數就可以使用 對象。swith()方法進行執行
gr1.switch()
運行結果:
gevent模塊
Gevent 是一個第三方庫,可以輕鬆通過gevent實現併發同步或異步編程,在gevent中用到的主要模式是Greenlet。
代碼演示:
import requests
import gevent
import time
def f(url):
print("get",url)
resp = requests.get(url)
data = resp.text
print("%d byte received from %s"%(len(data),url))
#1.普通模式
s = time.time()
f("http://www.langlang2017.com/img/banner1.png")
f("http://www.langlang2017.com/img/banner2.png")
f("http://www.langlang2017.com/img/banner3.png")
f("http://www.langlang2017.com/img/banner4.png")
e=time.time()
print("普通模式時間",e-s)
#2.使用gevent模塊
start = time.time()
gevent.joinall(
[gevent.span("http://www.langlang2017.com/img/banner1.png") ,#創建一個普通的greenlet對象並切換
gevent.span("http://www.langlang2017.com/img/banner2.png") ,
gevent.span("http://www.langlang2017.com/img/banner3.png") ]
)
print("gevent時間",time.time()-start)
運行結果:
今天先將這裏丫