190221协程与IO模型
一、协程
- 又称微线程
- 协程是一种用户态的轻量级的线程
- 在单线程下实现的并发,例如:yield
优点: - 无需线程上下文切换的开销
- 无需原子操作锁定及同步的开销
- 方便切换控制流,简化编程模型
- 高并发,高扩展性,低成本:一个CPU可支持上万的协程
缺点: - 无法利用多核资源
- 进行阻塞操作会阻塞掉整个程序
import time,queue
def consumer(name):
print('--->starting eating bun...')
while True:
new_bun = yield
print("[%s] is eating bun %s" %(name,new_bun))
def producer():
r = con.__next__()
r = con2.__next__()
n = 0
while n < 5:
n += 1
con.send(n)
con2.send(n)
print("\033[32;1m[producer]\033[0m is making bun %s" %n)
if __name__ == '__main__':
con = consumer("c1")
con2 = consumer("c2")
p = producer()
二、greenlet 手动切换
# Author:Li Dongfei
from greenlet import greenlet
def test1():
print(12)
gr2.switch() #切换至gr2
print(34)
gr2.switch()
def test2():
print(56)
gr1.switch()
print(78)
gr1 = greenlet(test1) #启动一个协程
gr2 = greenlet(test2)
gr1.switch() #切换至gr1
三、genent 自动切换
- 遇到sleep自动切换
# Author:Li Dongfei
import gevent
def foo():
print("Running in foo")
gevent.sleep(2)
print("Explicit context switch to foo again")
def bar():
print("Explicit精确的 context to bar")
gevent.sleep(1)
print("Implicit context switch back to bar")
def func():
print("in the func")
gevent.sleep(0)
print("in the func again")
gevent.joinall([
gevent.spawn(foo),
gevent.spawn(bar),
gevent.spawn(func),
])
- 协程并发爬网页
# Author:Li Dongfei
from gevent import monkey; monkey.patch_all() #把当前程序所有的io操作单独做标记,让gevent识别
import gevent
from urllib.request import urlopen
def f(url):
print('GET: %s' %url)
resp = urlopen(url)
data = resp.read()
f = open("url.html", "wb")
f.write(data)
f.close()
print('%d bytes received from %s.' %(len(data), url))
gevent.joinall([
gevent.spawn(f, 'https://www.python.org'),
gevent.spawn(f, 'https://www.github.com'),
gevent.spawn(f, 'https://www.aliyun.com'),
])
- 通过gevent实现单线程的多socket并发
- server
# Author:Li Dongfei
import sys,socket,time,gevent
from gevent import socket,monkey
monkey.patch_all()
def server(port):
s = socket.socket()
s.bind(('localhost', port))
s.listen(500)
while True:
cli, addr = s.accept()
gevent.spawn(handle_request, cli)
def handle_request(conn):
try:
while True:
data = conn.recv(1024)
print("recv:", data)
conn.send(data)
if not data:
conn.shutdown(socket.SHUT_WR)
except Exception as ex:
print(ex)
finally:
conn.close()
if __name__ == '__main__':
server(8001)
- client
# Author:Li Dongfei
import socket
HOST = 'localhost'
PORT = 8001
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((HOST, PORT))
while True:
msg = bytes(input(">>:"), encoding="utf-8")
s.sendall(msg)
data = s.recv(1024)
print('Received', data)
s.close()
四、I/O模型
- 阻塞
- 非阻塞
- I/O多路复用
- 信号驱动
- 异步
- Python select socket server代码示例
# Author:Li Dongfei
import select, socket, sys, queue
server = socket.socket()
server.bind(('localhost', 9000))
server.listen(1000)
server.setblocking(False) #设置为非阻塞
msg_dic = {}
inputs = [server,]
outputs = []
while True:
readable, writeable, exceptional = select.select(inputs, outputs, inputs)
print(readable,writeable,exceptional)
for r in readable:
if r is server:
conn, addr = server.accept()
print("new connect", addr)
inputs.append(conn)
msg_dic[conn] = queue.Queue()
else:
data = r.recv(1024)
print("recv data",data)
msg_dic[r].put(data)
outputs.append(r)
for w in writeable:
data_to_clinet =msg_dic[w].get()
w.send(data_to_clinet)
outputs.remove(w)
for e in exceptional:
if e in outputs:
outputs.remove(e)
inputs.remove(e)
del msg_dic[e]
五、selector模块
# Author:Li Dongfei
import selectors, socket
sel = selectors.DefaultSelector()
def accept(sock, mask):
conn, addr = sock.accept()
print('accepted', conn, 'from', addr)
conn.setblocking(False)
sel.register(conn, selectors.EVENT_READ, read)
def read(conn, mask):
data = conn.recv(1024)
if data:
print('echoing', repr(data), 'to', conn)
conn.send(data)
else:
print('closing', conn)
sel.unregister(conn)
conn.close()
sock = socket.socket()
sock.bind(('localhost', 9000))
sock.listen(1000)
sock.setblocking(False)
sel.register(sock, selectors.EVENT_READ, accept)
while True:
events = sel.select()
for key, mask in events:
callback = key.data
callback(key.fileobj, mask)
190221协程与IO模型的更多相关文章
- 并发编程 --进、线程池、协程、IO模型
内容目录: 1.socket服务端实现并发 2.进程池,线程池 3.协程 4.IO模型 1.socket服务端实现并发 # 客户端: import socket client = socket.soc ...
- Cpython解释器下实现并发编程——多进程、多线程、协程、IO模型
一.背景知识 进程即正在执行的一个过程.进程是对正在运行的程序的一个抽象. 进程的概念起源于操作系统,是操作系统最核心的概念,也是操作系统提供的最古老也是最重要的抽象概念之一.操作系统的其他所有内容都 ...
- Python并发编程二(多线程、协程、IO模型)
1.python并发编程之多线程(理论) 1.1线程概念 在传统操作系统中,每个进程有一个地址空间,而且默认就有一个控制线程 线程顾名思义,就是一条流水线工作的过程(流水线的工作需要电源,电源就相当于 ...
- 线程,协程,IO模型
理论: 1.每创造一个进程,默认里面就有一个线程 2.进程是一个资源单位,而进程里面的线程才是CPU上的一个调度单位 3.一个进程里面的多个线程,是共享这个进程里面的资源的 4.线程创建的开销比进程要 ...
- 协程和IO模型
协程 1.什么是协程 单线程实现并发 在应用程序里控制多个任务的切换+保存状态 优点: 应用程序级别速度要远远高于操作系统的切换 缺点: 多个任务一旦有一个阻塞没有切,整个线程都阻塞在原地 该线程内的 ...
- Python 协程、IO模型
1.协程(单线程实现并发)2.I/0模型 2.1阻塞I/O 2.2非阻塞I/O 知识点一:协程 协程的目的:是想要在单线程下实现并发(并发看起来是同时运行的) 并发=多个任务间切换+保存状态(正常情况 ...
- python(40)- 进程、线程、协程及IO模型
一.操作系统概念 操作系统位于底层硬件与应用软件之间的一层.工作方式:向下管理硬件,向上提供接口. 操作系统进行进程切换:1.出现IO操作:2.固定时间. 固定时间很短,人感受不到.每一个应用层运行起 ...
- 网络编程进阶:并发编程之协程、IO模型
协程: 基于单线程实现并发,即只用一个主线程(此时可利用的CPU只有一个)情况下实现并发: 并发的本质:切换+保存状态 CPU正在运行一个任务,会在两种情况下切走去执行其他任务(切换有操作系统强制控制 ...
- day33_8_15 并发编程4,线程池与协程,io模型
一.线程池 线程池是一个处理线程任务的集合,他是可以接受一定量的线程任务,并创建线程,处理该任务,处理结束后不会立刻关闭池子,会继续等待提交的任务,也就是他们的进程/线程号不会改变. 当线程池中的任务 ...
随机推荐
- Oracle11gR2--克隆安装数据库软件
1. 删除oracle之前的产品信息 环境是前篇中通过静默方式安装的,这里只删除产品信息,假设ORACLE_HOME目录是从其他地方拷贝过来的 [oracle@localhost ContentsXM ...
- apache配置多个虚拟主机 localhost访问不了解决方案
在httpd-vhosts.conf,重定向localhost <VirtualHost *:80> ServerAdmin webmaster@dummy-host2.exampl ...
- 有一些sql 是必须要做笔记的!!
select CONCAT(unix_timestamp(),"-",id,"-",name) as aa,age from workers; //连接字段 s ...
- docker-compose之Nginx+Tomcat代理配置
Tomcat镜像制作与启动 Dockerfile如下 FROM docker.io/sssllc/centos7.-jdk1. #update RUN yum -y update; yum clean ...
- laravel 中的Gates,以及修改模型
Gates 是一个用于判断用户是否有权进行某项操作的闭包,通常使用Gate 门面定义在 App\Providers\AuthServiceProvider类中.Gates 总是接收用户实例作为第一个参 ...
- 2014蓝桥杯B组初赛试题《李白打酒》
题目描述: 话说大诗人李白,一生好饮.幸好他从不开车. 一天,他提着酒壶,从家里出来,酒壶中有酒2斗.他边走边唱: 无事街上走,提壶去打酒. 逢店加一倍,遇花喝一斗. 这一路上 ...
- mysql sandbox的问题备忘
工具很好用,但是安装运行时有些小问题: 1.启动数据库时提示--bootstrap已禁用:那是mysql5.7以后废弃了此参数,改用--initialize来初始化了,而一般公共仓库里的sandbox ...
- Luogu 4254 [JSOI2008]Blue Mary开公司
BZOJ 1568 学习了一波李超线段树. 大佬blog 这个东西专门用来维护插入一条线段和区间/单点的最大/最小值. 插入的时候讨论: 1.如果当前结点上没有线段,那么直接插入. 2.如果当前结点上 ...
- 在Asp.Net中使用amChart统计图
怎么在自己的ASP.NET页面插入可动态更新的数据统计图呢?网上的资源倒是不少(Fusioncharts.amCharts……),在这些资源中有一个比较好用:amChart,这个工具很炫,还能与用户交 ...
- input file 获取不到Request.Files 解决办法
<input type="file" name="xxxxxxx"/>必须有“name”属性,否则在后台代码中用Request.Files是取不到值 ...