一。协程
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模型
最新推荐文章于 2022-01-21 21:56:44 发布
1004

被折叠的 条评论
为什么被折叠?



