一。协程 1、协程: 单线程实现并发 在应用程序里控制多个任务的切换+保存状态 优点: 应用程序级别速度要远远高于操作系统的切换 缺点: 多个任务一旦有一个阻塞没有切,整个线程都阻塞在原地 该线程内的其他的任务都不能执行了 一旦引入协程,就需要检测单线程下所有的IO行为, 实现遇到IO就切换,少一个都不行,以为一旦一个任务阻塞了,整个线程就阻塞了, 其他的任务即便是可以计算,但是也无法运行了 2、协程序的目的: 想要在单线程下实现并发 并发指的是多个任务看起来是同时运行的 并发=切换+保存状态 二。导入模块来实现单线程并发 利用gevent来实现单线程并发 导入monkey.patch_all()来实现所有的IO都可以识别 from gevent import monkey,spawn;monkey.patch_all() from threading import current_thread import time def eat(): print('%s eat 1' %current_thread().name) time.sleep(3) print('%s eat 2' %current_thread().name) def play(): print('%s play 1' %current_thread().name) time.sleep(1) print('%s play 2' %current_thread().name) g1=spawn(eat,) g2=spawn(play,) print(current_thread().name) 三,单线程下实现并发的套接字 服务端 from gevent import spawn,monkey;monkey.patch_all() from socket import * from threading import Thread def talk(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) print('starting...') while True: conn, addr = server.accept() spawn(talk, conn,) if __name__ == '__main__': g=spawn(server,'127.0.0.1',8080) g.join() 客户端 from threading import Thread,current_thread from socket import * import os def task(): client=socket(AF_INET,SOCK_STREAM) client.connect(('127.0.0.1',8080)) while True: msg='%s say hello' %current_thread().name 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=task) t.start() IO模型的介绍 网络IO: recvfrom: wait data:等待客户端产生数据——》客户端OS--》网络--》服务端操作系统缓存 copy data:由本地操作系统缓存中的数据拷贝到应用程序的内存中 send: copy data 非阻塞IO模型 服务端 from socket import * import time server = socket(AF_INET, SOCK_STREAM) server.bind(('127.0.0.1',8080)) server.listen(5) server.setblocking(False) conn_l=[] while True: try: print('总连接数[%s]' % len(conn_l)) conn,addr=server.accept() conn_l.append(conn) except BlockingIOError: del_l=[] for conn in conn_l: try: data=conn.recv(1024) if len(data) == 0: del_l.append(conn) continue conn.send(data.upper()) except BlockingIOError: pass except ConnectionResetError: del_l.append(conn) for conn in del_l: conn_l.remove(conn)
协程与IO模型
猜你喜欢
转载自blog.csdn.net/qq_35540539/article/details/81087474
今日推荐
周排行