程序員
web
多線程
併發
異步
socket
ide
高併發
spa
操作系統
任務是計算密集型,反而會下降效率
任務是IO密集型,會提高效率
1)yield可以實現保存上次運行狀態,可是沒法識別io
# 串行執行 import time def func1(): for i in range(10000000): i + 1 def func2(): for i in range(10000000): i + 1 start = time.time() func1() func2() stop = time.time() print(stop - start) # 基於yield併發執行 import time def func1(): while True: 10000000 + 1 yield def func2(): g = func1() for i in range(10000000): time.sleep(100) # 模擬IO,yield並不會捕捉到並自動切換 i + 1 next(g) start = time.time() func2() stop = time.time() print(stop - start)
2)單線程下實現併發
若是你可以本身經過代碼層面監測你本身的io行爲
而且經過代碼實現切換+保存狀態
單線程實現高併發
# ---------------服務端--------------------- from gevent import monkey; monkey.patch_all() from gevent import spawn import socket def communicate(conn): while True: try: data = conn.recv(1024) if len(data) == 0: break print(data.decode('utf-8')) conn.send(data.upper()) except ConnectionResetError: break conn.close() def server(): server = socket.socket() server.bind(('127.0.0.1', 8080)) server.listen(5) while True: conn, addr = server.accept() spawn(communicate, conn) if __name__ == '__main__': s1 = spawn(server) s1.join() # ---------------客戶端--------------------- from threading import Thread, current_thread import socket def client(): client = socket.socket() client.connect(('127.0.0.1', 8080)) n = 1 while True: data = '%s %s' % (current_thread().name, n) n += 1 client.send(data.encode('utf-8')) info = client.recv(1024) print(info) if __name__ == '__main__': for i in range(500): t = Thread(target=client) t.start()
3)gevent模塊的使用
spawn:幫你管理任務的對象
gevent模塊不能識別它自己之外的全部的IO行爲,可是它內部封裝了一個模塊,可以幫助咱們識別全部的IO行爲
from gevent import monkey; monkey.patch_all() # 監測代碼中全部io行爲 from gevent import spawn # gevent自己識別不了time.sleep等不屬於該模塊內的io操做 import time def heng(name): print('%s 哼' % name) time.sleep(2) print('%s 哼' % name) def ha(name): print('%s 哈' % name) time.sleep(3) print('%s 哈' % name) start = time.time() s1 = spawn(heng, 'Tom') s2 = spawn(ha, 'Bob') s1.join() s2.join() # heng('Tom') # ha('Bob') print('主', time.time() - start)
4)
# 服務端 from gevent import monkey;monkey.patch_all() from socket import * # !!!後 from gevent import spawn def communicate(conn): while True: try: data = conn.recv(1024) if len(data) == 0: break conn.send(data.upper()) except ConnectionResetError: break conn.close() def server(ip, port, backlog=5): server = socket(AF_INET, SOCK_STREAM) server.bind((ip, port)) server.listen(backlog) while True: # 連接循環 conn, client_addr = server.accept() print(client_addr) # 通訊 spawn(communicate,conn) if __name__ == '__main__': g1=spawn(server,'127.0.0.1',8080) g1.join() # 客戶端 from threading import Thread, current_thread from socket import * def client(): client = socket(AF_INET, SOCK_STREAM) client.connect(('127.0.0.1', 8080)) n = 0 while True: msg = '%s say hello %s' % (current_thread().name, n) n += 1 client.send(msg.encode('utf-8')) data = client.recv(1024) print(data.decode('utf-8')) if __name__ == '__main__': for i in range(500): t = Thread(target=client) t.start()
阻塞IO Blocking I/O非阻塞IO 服務端通訊針對accept用s.setblocking(False)加異常捕獲,cpu佔用率太高IO多路複用 multiplexing I/O 在只檢測一個套接字的狀況下,他的效率連阻塞IO都比不上。由於select這個中間人增長了環節。 可是在檢測多個套接字的狀況下,就能省去wait for data過程異步IO Asynchronous I/O