當(dāng)前位置:
首頁 >
并发编程 - 协程 - 1.协程概念/2.greenlet模块/3.gevent模块/4.gevent实现并发的套接字通信...
發(fā)布時(shí)間:2025/7/14
38
豆豆
生活随笔
收集整理的這篇文章主要介紹了
并发编程 - 协程 - 1.协程概念/2.greenlet模块/3.gevent模块/4.gevent实现并发的套接字通信...
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
1.協(xié)程
并發(fā):切+保存狀態(tài)
單線程下實(shí)現(xiàn)并發(fā):協(xié)程 切+ 保存狀態(tài) yield
遇到io切,提高效率
遇到計(jì)算切,并沒有提高效率
檢測單線程下 IO行為 io阻塞 切
相當(dāng)于騙操作系統(tǒng) 一直處于計(jì)算
協(xié)程:。。。
單線程下實(shí)現(xiàn)并發(fā):根本目標(biāo):遇到IO就切,一個(gè)線程的整體IO降下來
程序用的cpu 時(shí)間長,就叫執(zhí)行效率高
效率最高:多個(gè)進(jìn)程 (多個(gè)cpu)
每個(gè)進(jìn)程開多個(gè)線程
每個(gè)線程用到協(xié)程 (IO就切)
總結(jié)協(xié)程特點(diǎn): 1 #并發(fā)執(zhí)行 2 import time 3 4 def producer(): 5 g=consumer() 6 next(g) 7 for i in range(10000000): # 計(jì)算 8 g.send(i) 9 10 11 def consumer(): 12 while True: 13 res=yield 14 15 16 start_time=time.time() 17 producer() 18 stop_time=time.time() 19 print(stop_time-start_time) 20 21 #串行 22 import time 23 24 def producer(): 25 res=[] 26 for i in range(10000000): 27 res.append(i) 28 return res 29 30 31 def consumer(res): 32 pass 33 34 35 start_time=time.time() 36 res=producer() 37 consumer(res) 38 stop_time=time.time() 39 print(stop_time-start_time)
pip3 install greenlet
greenlet:可以很方便的切 但不能檢測到 遇到IO 切
greenlet 比yield 好 但是還是不好 遇到io不會(huì)切 1 from greenlet import greenlet 2 import time 3 4 def eat(name): 5 print('%s eat 1' %name) 6 time.sleep(10) # 遇到io 不會(huì)立即切 7 g2.switch('egon') 8 print('%s eat 2' %name) 9 g2.switch() 10 11 def play(name): 12 print('%s play 1' %name ) 13 g1.switch() 14 print('%s play 2' %name ) 15 16 17 g1=greenlet(eat) 18 g2=greenlet(play) 19 20 g1.switch('egon') # 第一次切 需要傳參數(shù)
pip3 install gevent
gevent:封裝了greenlet模塊,但是他能檢測到io 自動(dòng)切
只能檢測到gevent.sleep() gevent的IO阻塞
加上補(bǔ)丁后,就可以檢測到所有的IO 原理是:將阻塞變?yōu)榉亲枞?br /> from gevent import monkey;monkey.patch_all()
這種形式的協(xié)程 才能幫我們提升效率 從始至終 就一個(gè)線程
gevent.joinall([g1,g2]) 等待全部執(zhí)行完
gevent 模塊:監(jiān)測單線程下多個(gè)任務(wù)得IO行為實(shí)現(xiàn)遇到IO就自動(dòng)切到另一個(gè)任務(wù)去執(zhí)行
提升單線程運(yùn)行效率
應(yīng)用場景:單線程下多個(gè)任務(wù)io密集型
ftp io密集型 線程來回切 比os q切 小路高 1 from gevent import monkey;monkey.patch_all() # 一定要放在程序的開頭 檢測所以的io 將阻塞變成非阻塞 2 import gevent 3 import time 4 5 6 def eat(name): 7 print('%s eat 1' % name) 8 time.sleep(3) # 7s多一些 gevent 只識(shí)別 gevent 的 io操作 9 # gevent.sleep(3) # 4s 多一些 10 print('%s eat 2' % name) 11 12 13 def play(name): 14 print('%s play 1' % name) 15 time.sleep(4) 16 # gevent.sleep(4) 17 print('%s play 2' % name) 18 19 20 start_time=time.time() 21 g1=gevent.spawn(eat,'egon') 22 g2=gevent.spawn(play,'alex') 23 24 g1.join() 25 g2.join() 26 stop_time=time.time() 27 print(stop_time-start_time) 28 """ 29 egon eat 1 30 alex play 1 31 egon eat 2 32 alex play 2 33 4.001747369766235 34 35 """ 36 """ 37 egon eat 1 38 egon eat 2 39 alex play 1 40 alex play 2 41 7.0017828941345215 42 """ 43 """ 44 egon eat 1 45 alex play 1 46 egon eat 2 47 alex play 2 48 4.001675367355347 49 """ 50 51 from gevent import monkey;monkey.patch_all() 52 import gevent 53 import time 54 55 56 def eat(name): 57 print('%s eat 1' % name) 58 time.sleep(3) 59 print('%s eat 2' % name) 60 61 62 def play(name): 63 print('%s play 1' % name) 64 time.sleep(4) 65 print('%s play 2' % name) 66 67 68 g1=gevent.spawn(eat,'egon') # 異步操作 69 g2=gevent.spawn(play,'alex') 70 71 # time.sleep(5) # 得等到 全部執(zhí)行完 72 73 # g1.join() # 等到 全部執(zhí)行完 74 # g2.join() 75 76 gevent.joinall([g1,g2]) # 等到g1 g2 全部執(zhí)行完 77 """ 78 egon eat 1 79 alex play 1 80 egon eat 2 81 alex play 2 82 """
# 500 客戶端同時(shí) 登錄 服務(wù)端:這里1個(gè)線程 抗住了 500個(gè)client
# 這里也說明了:單線程下面io問題降下來,效率大幅度提高
說明
使用:多進(jìn)程
多線程
一個(gè)線程io 問題解決了 效率大大得提高
服務(wù)端: 1 #基于gevent實(shí)現(xiàn) 2 from gevent import monkey,spawn;monkey.patch_all() 3 from socket import * 4 5 def communicate(conn): 6 while True: 7 try: 8 data=conn.recv(1024) 9 if not data:break 10 conn.send(data.upper()) 11 except ConnectionResetError: 12 break 13 14 conn.close() 15 16 def server(ip,port): 17 server = socket(AF_INET, SOCK_STREAM) 18 server.bind((ip,port)) 19 server.listen(5) 20 21 while True: 22 conn, addr = server.accept() 23 spawn(communicate,conn) # 這里沒必要加join 24 25 server.close() 26 27 if __name__ == '__main__': 28 g=spawn(server,'127.0.0.1',8090) 29 g.join() 客戶端: 1 from socket import * 2 from threading import Thread,currentThread 3 4 def client(): # 5 client=socket(AF_INET,SOCK_STREAM) 6 client.connect(('127.0.0.1',8090)) 7 8 9 while True: 10 client.send(('%s hello' %currentThread().getName()).encode('utf-8')) 11 data=client.recv(1024) 12 print(data.decode('utf-8')) 13 14 client.close() 15 16 # 500 客戶端同時(shí) 登錄 服務(wù)端:這里1個(gè)線程 抗住了 500個(gè)client 17 # 這里也說明了:單線程下面io問題降下來,效率大幅度提高 18 if __name__ == '__main__': 19 for i in range(500): # 500 客戶端同時(shí) 登錄 服務(wù)端:這里1個(gè)線程 抗住了 500個(gè)client 20 t=Thread(target=client) 21 t.start()
并發(fā):切+保存狀態(tài)
單線程下實(shí)現(xiàn)并發(fā):協(xié)程 切+ 保存狀態(tài) yield
遇到io切,提高效率
遇到計(jì)算切,并沒有提高效率
檢測單線程下 IO行為 io阻塞 切
相當(dāng)于騙操作系統(tǒng) 一直處于計(jì)算
協(xié)程:。。。
單線程下實(shí)現(xiàn)并發(fā):根本目標(biāo):遇到IO就切,一個(gè)線程的整體IO降下來
程序用的cpu 時(shí)間長,就叫執(zhí)行效率高
效率最高:多個(gè)進(jìn)程 (多個(gè)cpu)
每個(gè)進(jìn)程開多個(gè)線程
每個(gè)線程用到協(xié)程 (IO就切)
總結(jié)協(xié)程特點(diǎn): 1 #并發(fā)執(zhí)行 2 import time 3 4 def producer(): 5 g=consumer() 6 next(g) 7 for i in range(10000000): # 計(jì)算 8 g.send(i) 9 10 11 def consumer(): 12 while True: 13 res=yield 14 15 16 start_time=time.time() 17 producer() 18 stop_time=time.time() 19 print(stop_time-start_time) 20 21 #串行 22 import time 23 24 def producer(): 25 res=[] 26 for i in range(10000000): 27 res.append(i) 28 return res 29 30 31 def consumer(res): 32 pass 33 34 35 start_time=time.time() 36 res=producer() 37 consumer(res) 38 stop_time=time.time() 39 print(stop_time-start_time)
?
2.greenlet模塊pip3 install greenlet
greenlet:可以很方便的切 但不能檢測到 遇到IO 切
greenlet 比yield 好 但是還是不好 遇到io不會(huì)切 1 from greenlet import greenlet 2 import time 3 4 def eat(name): 5 print('%s eat 1' %name) 6 time.sleep(10) # 遇到io 不會(huì)立即切 7 g2.switch('egon') 8 print('%s eat 2' %name) 9 g2.switch() 10 11 def play(name): 12 print('%s play 1' %name ) 13 g1.switch() 14 print('%s play 2' %name ) 15 16 17 g1=greenlet(eat) 18 g2=greenlet(play) 19 20 g1.switch('egon') # 第一次切 需要傳參數(shù)
?
3.gevent模塊pip3 install gevent
gevent:封裝了greenlet模塊,但是他能檢測到io 自動(dòng)切
只能檢測到gevent.sleep() gevent的IO阻塞
加上補(bǔ)丁后,就可以檢測到所有的IO 原理是:將阻塞變?yōu)榉亲枞?br /> from gevent import monkey;monkey.patch_all()
這種形式的協(xié)程 才能幫我們提升效率 從始至終 就一個(gè)線程
gevent.joinall([g1,g2]) 等待全部執(zhí)行完
gevent 模塊:監(jiān)測單線程下多個(gè)任務(wù)得IO行為實(shí)現(xiàn)遇到IO就自動(dòng)切到另一個(gè)任務(wù)去執(zhí)行
提升單線程運(yùn)行效率
應(yīng)用場景:單線程下多個(gè)任務(wù)io密集型
ftp io密集型 線程來回切 比os q切 小路高 1 from gevent import monkey;monkey.patch_all() # 一定要放在程序的開頭 檢測所以的io 將阻塞變成非阻塞 2 import gevent 3 import time 4 5 6 def eat(name): 7 print('%s eat 1' % name) 8 time.sleep(3) # 7s多一些 gevent 只識(shí)別 gevent 的 io操作 9 # gevent.sleep(3) # 4s 多一些 10 print('%s eat 2' % name) 11 12 13 def play(name): 14 print('%s play 1' % name) 15 time.sleep(4) 16 # gevent.sleep(4) 17 print('%s play 2' % name) 18 19 20 start_time=time.time() 21 g1=gevent.spawn(eat,'egon') 22 g2=gevent.spawn(play,'alex') 23 24 g1.join() 25 g2.join() 26 stop_time=time.time() 27 print(stop_time-start_time) 28 """ 29 egon eat 1 30 alex play 1 31 egon eat 2 32 alex play 2 33 4.001747369766235 34 35 """ 36 """ 37 egon eat 1 38 egon eat 2 39 alex play 1 40 alex play 2 41 7.0017828941345215 42 """ 43 """ 44 egon eat 1 45 alex play 1 46 egon eat 2 47 alex play 2 48 4.001675367355347 49 """ 50 51 from gevent import monkey;monkey.patch_all() 52 import gevent 53 import time 54 55 56 def eat(name): 57 print('%s eat 1' % name) 58 time.sleep(3) 59 print('%s eat 2' % name) 60 61 62 def play(name): 63 print('%s play 1' % name) 64 time.sleep(4) 65 print('%s play 2' % name) 66 67 68 g1=gevent.spawn(eat,'egon') # 異步操作 69 g2=gevent.spawn(play,'alex') 70 71 # time.sleep(5) # 得等到 全部執(zhí)行完 72 73 # g1.join() # 等到 全部執(zhí)行完 74 # g2.join() 75 76 gevent.joinall([g1,g2]) # 等到g1 g2 全部執(zhí)行完 77 """ 78 egon eat 1 79 alex play 1 80 egon eat 2 81 alex play 2 82 """
?
4.gevent實(shí)現(xiàn)并發(fā)的套接字通信# 500 客戶端同時(shí) 登錄 服務(wù)端:這里1個(gè)線程 抗住了 500個(gè)client
# 這里也說明了:單線程下面io問題降下來,效率大幅度提高
說明
使用:多進(jìn)程
多線程
一個(gè)線程io 問題解決了 效率大大得提高
服務(wù)端: 1 #基于gevent實(shí)現(xiàn) 2 from gevent import monkey,spawn;monkey.patch_all() 3 from socket import * 4 5 def communicate(conn): 6 while True: 7 try: 8 data=conn.recv(1024) 9 if not data:break 10 conn.send(data.upper()) 11 except ConnectionResetError: 12 break 13 14 conn.close() 15 16 def server(ip,port): 17 server = socket(AF_INET, SOCK_STREAM) 18 server.bind((ip,port)) 19 server.listen(5) 20 21 while True: 22 conn, addr = server.accept() 23 spawn(communicate,conn) # 這里沒必要加join 24 25 server.close() 26 27 if __name__ == '__main__': 28 g=spawn(server,'127.0.0.1',8090) 29 g.join() 客戶端: 1 from socket import * 2 from threading import Thread,currentThread 3 4 def client(): # 5 client=socket(AF_INET,SOCK_STREAM) 6 client.connect(('127.0.0.1',8090)) 7 8 9 while True: 10 client.send(('%s hello' %currentThread().getName()).encode('utf-8')) 11 data=client.recv(1024) 12 print(data.decode('utf-8')) 13 14 client.close() 15 16 # 500 客戶端同時(shí) 登錄 服務(wù)端:這里1個(gè)線程 抗住了 500個(gè)client 17 # 這里也說明了:單線程下面io問題降下來,效率大幅度提高 18 if __name__ == '__main__': 19 for i in range(500): # 500 客戶端同時(shí) 登錄 服務(wù)端:這里1個(gè)線程 抗住了 500個(gè)client 20 t=Thread(target=client) 21 t.start()
?
轉(zhuǎn)載于:https://www.cnblogs.com/mumupa0824/p/9401008.html
總結(jié)
以上是生活随笔為你收集整理的并发编程 - 协程 - 1.协程概念/2.greenlet模块/3.gevent模块/4.gevent实现并发的套接字通信...的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【JavaScript】jQuery绑定
- 下一篇: jQuery单选按钮监听事件