多线程和协程都属于IO密集型,我通过以下用例测试多线程和协程的实际速率对比。
实例:通过socket客户端以多线程并发模式请求不同服务器端(这里服务器端分2种写法:第一种服务器通过协程实现,第二种服务器通过多线程实现)的访问速率
第一种服务器端写法:通过gevent实现
1 import socket 2 import gevent 3 from gevent import socket, monkey 4 monkey.patch_all() 5 6 def server(port): # socket服务器函数 7 s = socket.socket() 8 s.bind(('localhost', port)) 9 s.listen() 10 print('start server listen:') 11 while True: 12 conn, addr = s.accept() 13 gevent.spawn(handle_request, conn) # 协程模式实现交互 14 15 def handle_request(conn): 16 try: 17 while True: 18 data = conn.recv(1024) 19 print('recv:',data) 20 conn.send(data) 21 if not data: 22 conn.shutdown(socket.SHUT_WR) 23 except Exception as e: 24 print(e) 25 finally: 26 conn.close() 27 if __name__ == '__main__': 28 server(9999)
第二种服务器端写法:通过多线程实现
1 import socketserver 2 3 class Myhandler(socketserver.BaseRequestHandler): 4 def handle(self): 5 print(self) 6 while True: 7 print('开始监听客户端连接') 8 data = self.request.recv(1024) 9 # if len(data) == 0: 10 # exit('client close') 11 print('client data:', data) 12 self.request.send(data.upper()) 13 14 15 if __name__ == '__main__': 16 s = socketserver.ThreadingTCPServer(('localhost', 9999), Myhandler) # 多线程 17 s.serve_forever()
客户端:
1 import socket, time 2 import threading 3 4 def client(): 5 c = socket.socket() 6 c.connect(('localhost',9999)) 7 count = 0 8 while count < 10: 9 c.send(("hello %s" % count).encode('utf-8')) 10 data = c.recv(1024) 11 print('recv from server:%s' % data) 12 count += 1 13 c.close() 14 15 res_l = [] 16 start_time = time.time() 17 for i in range(100): 18 t = threading.Thread(target=client) 19 t.start() 20 res_l.append(t) 21 for j in res_l: 22 j.join() 23 end_time = time.time() 24 print('finish,run time:', end_time-start_time)
结果:客户端每次运行,自动生成100个线程并发执行,每个线程自循环10次访问,对协程模式服务器的执行一次时长为: 0.17600011825561523秒, 对多线程服务器执行一次时长为:1.312999963760376 秒,通过结果对比协程模式实现的socket服务器处理速率远远高于多线程服务器