一、協(xié)程
協(xié)程,又叫微線程,纖程。英文名Coroutine。協(xié)程本質(zhì)上就是一個線程
優(yōu)點1:協(xié)程極高的執(zhí)行效率。因為子程序切換不是線程切換,而是由程序自身控制,因此,沒有線程切換的開銷,和多線程比,線程數(shù)量越多,協(xié)程的性能優(yōu)勢就越來越明顯。(簡單來說沒有切換的消耗)
優(yōu)點2:不需要多線程的鎖機制,因為只有一個線程,也不存在同時寫變量沖突,在協(xié)程中控制共享資源不加鎖,只需要判斷狀態(tài)就好,所以執(zhí)行效率比多線程高很多。(沒有鎖的概念)
因為協(xié)程是一個線程執(zhí)行,那怎么利用多核CPU呢?最簡單的方法是多進程+協(xié)程,既充分利用多核,又充分發(fā)揮協(xié)程的高效率,可獲得極高的性能。
二、yield的簡單實現(xiàn)
#_*_ coding:utf-8 _*_
# Author:Simon
# Datetime:2019/9/2 21:07
# Software:PyCharm
import
time
import
queue
def
consumer(name):
print("--->ready to eat baozi..."
)
while
True:
new_baozi = yield
print("[%s] is eating baozi %s" %
(name,new_baozi)) #time.sleep(1) def
producer(): r = con.__next__
() r = con2.__next__
() n =
0 while 1
: time.sleep(1
) print("\033[32;1m[producer]\033[0m is making baozi %s and %s" %(n,n+1
) ) con.send(n) con2.send(n+1
) n +=2 if __name__ == '__main__'
: con = consumer("c1"
) con2 = consumer("c2"
) p = producer()
三、Greenlet模塊
greenlet是一個用C實現(xiàn)的協(xié)程模塊,相比與python自帶的yield,它可以使你在任意函數(shù)之間隨意切換,而不需把這個函數(shù)先聲明為generator
#_*_ coding:utf-8 _*_
# Author:Simon
# Datetime:2019/9/2 21:29
# Software:PyCharm
from greenlet import
greenlet
def
test1():
print(12
)
gr2.switch()
print(34
)
gr2.switch()
def
test2():
print(56
) gr1.switch() print(78
) gr1 =
greenlet(test1) gr2 =
greenlet(test2) gr1.switch()
四、Gevent模塊
本質(zhì)就是封裝了greenlet模塊,它能檢測I/O并且遇到I/O自動切換到另外一個任務(wù)執(zhí)行;可以幫我們提升效率
#_*_ coding:utf-8 _*_
# Author:Simon
# Datetime:2019/9/2 21:39
# Software:PyCharm
import
gevent
import
requests,time
start=
time.time()
def
f(url):
print('GET: %s' %
url)
resp =
requests.get(url) data =
resp.text print('%d bytes received from %s.' %
(len(data), url)) gevent.joinall([ gevent.spawn(f, 'https://www.jd.org/'
), gevent.spawn(f, 'https://www.xiaohua.com/'
), gevent.spawn(f, 'https://www.baidu.com/'
), gevent.spawn(f, 'https://www.taobao.com/'
), ]) # f('https://www.jd.org/') # f('https://www.xiaohua.com/') # f('https://baidu.com/') # f('https://www.taobao.com/') # # print("cost time:",time.time()-start)
gevent異步提交任務(wù)
from gevent import
monkey;monkey.patch_all()
import
gevent
import
time
def
eat(name):
print('%s eat 1' %
name)
time.sleep(3
) print('%s eat 2' %
name) def
play(name): print('%s play 1' %
name) time.sleep(4
) print('%s play 2' %
name) g1=gevent.spawn(eat,'simon'
) g2=gevent.spawn(play,'zhuzhu'
) # time.sleep(5) # g1.join() # g2.join()
gevent.joinall([g1,g2]) #相當(dāng)于上邊兩行代碼
打印: simon eat 1
zhuzhu play 1
simon eat 2
zhuzhu play 2
基于gevent模塊實現(xiàn)并發(fā)的套接字通信
單線程、多任務(wù)的I/O操作。
#基于gevent實現(xiàn)
from gevent import
monkey,spawn;monkey.patch_all()
from socket import *
def
communicate(conn):
while
True:
try
:
data=conn.recv(1024
)
if not data:break
conn.send(data.upper()) except
ConnectionResetError: break
conn.close() def
server(ip,port): server =
socket(AF_INET, SOCK_STREAM) server.bind((ip,port)) server.listen(5
) while
True: conn, addr =
server.accept() spawn(communicate,conn) #造一個協(xié)程對象,提交完這個對象它不會執(zhí)行
server.close() if __name__ == '__main__'
: g=spawn(server,'127.0.0.1',8090
) g.join()
##客戶端
from socket import *
from threading import
Thread,currentThread
def
client():
client=
socket(AF_INET,SOCK_STREAM)
client.connect(('127.0.0.1',8090
))
while
True:
client.send(('%s hello' %currentThread().getName()).encode('utf-8'
)) data=client.recv(1024
) print(data.decode('utf-8'
)) client.close() if __name__ == '__main__'
: for i in range(500
): t=Thread(target=
client) t.start()
?
更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯(lián)系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
