說明
協程最大的優勢就是協程極高的執行效率。因爲子程序切換不是線程切換,而是由程序自身控制,因此,沒有線程切換的開銷,和多線程比,線程數量越多,協程的性能優勢就越明顯。
第二大優勢就是不需要多線程的鎖機制,因爲只有一個線程,也不存在同時寫變量衝突,在協程中控制共享資源不加鎖,只需要判斷狀態就好了,所以執行效率比多線程高很多。
因爲協程是一個線程執行,那怎麼利用多核CPU呢?最簡單的方法是多進程+協程,既充分利用多核,又充分發揮協程的高效率,可獲得極高的性能。
用yield來實現協程
廖雪峯網站的例子
import time
def consumer():
r = ''
while True:
n = yield r
if not n:
return
print('[CONSUMER] Consuming %s...' % n)
time.sleep(1)
r = '200 OK'
def produce(c):
c.next()
n = 0
while n < 5:
n = n + 1
print('[PRODUCER] Producing %s...' % n)
r = c.send(n)
print('[PRODUCER] Consumer return: %s' % r)
c.close()
if __name__=='__main__':
c = consumer()
produce(c)
結果:
[PRODUCER] Producing 1...
[CONSUMER] Consuming 1...
[PRODUCER] Consumer return: 200 OK
[PRODUCER] Producing 2...
[CONSUMER] Consuming 2...
[PRODUCER] Consumer return: 200 OK
[PRODUCER] Producing 3...
[CONSUMER] Consuming 3...
[PRODUCER] Consumer return: 200 OK
[PRODUCER] Producing 4...
[CONSUMER] Consuming 4...
[PRODUCER] Consumer return: 200 OK
[PRODUCER] Producing 5...
[CONSUMER] Consuming 5...
[PRODUCER] Consumer return: 200 OK
首先調用c.next()啓動生成器;
然後,一旦生產了東西,通過c.send(n)切換到consumer執行;
consumer通過yield拿到消息,處理,又通過yield把結果傳回;
produce拿到consumer處理的結果,繼續生產下一條消息;
produce決定不生產了,通過c.close()關閉consumer,整個過程結束。
Python庫gevent
有了gevent爲我們自動切換協程,而不是在遇到IO操作
例子來源於網絡
import gevent
import time
def func1():
print('\033[31;1m 正在執行 111...\033[0m')
gevent.sleep(2)
print('\033[31;1m 正在執行 444...\033[0m')
def func2():
print('\033[32;1m 正在執行 222...\033[0m')
gevent.sleep(3) #阻塞3秒,所以自動切換到func1,執行完func1後 再切換回來
print('\033[32;1m 正在執行 333...\033[0m')
start_time = time.time()
gevent.joinall([
gevent.spawn(func1),
gevent.spawn(func2),
# gevent.spawn(func3),
])
end_time = time.time()
#程序總共花費3秒執行
print "spend",(end_time-start_time),"second"