标签:调度 函数 阻塞 自己的 提升 str ack done 自动
本质:在单线程下,由用户自己控制一个任务遇到io阻塞了就切换另外一个任务去执行,以此来提升效率
目的:减少操作系统切换的开销,规避IO操作,将一条线程中的io操作 降到最低
定义
协程的切换
运行
/ \ 阻塞——就绪
# 进程为等待输入而阻塞
# 调度程序选择里一个进程
# 调度程序选择另一个进程
# 出现有效输入
--------------
# gevent = 利用了 greenlet 底层模块完成的切换 + 自动规避io的功能
# asyncio = 利用了 yield 底层语法完成的切换 + 自动规避io的功能
协程优点
协程缺点
可以轻松通过gevent实现并发同步后异步编程,在gevent中用到的主要模式是Greenlet, 它是以C扩展模块形式接入Python的轻量级协程
用法 :gevent.spawn(函数名,参数)
def func(a,b,c,x=3):pass
g1 = gevent.spawn(func,1,3,4,x=5) # 创建一个协程对象g1
补丁
# gevent.sleep()模拟的是gevent可以识别的io阻塞,但time.sleep(2)或其他的阻塞不能被gevent直接识别,所以需要打补丁
from gevent import monkey
monkey.pstch_all() # 最好放在文件开头,这样后面indeed所有阻塞全部能够识别了
import time,socket
import asyncio
async def func(name):
print(‘start‘,name)
# await 可能会发生阻塞的方法
# await 关键字必须写在一个async函数里
await asyncio.sleep(2)
print(‘end‘)
lo = asyncio.get_event_loop()
lo.run_until_complete(asyncio.wait([func(‘alex‘),func(‘太白‘)]))
在程序开始的时候,还没提交任务先创建几个线程或者进程放在池中
发展过程
池的好处
线程池
import time
from threading import current_thread
from concurrent.futures import ThreadPoolExecutor
def func(a,b):
print(current_thread().ident,‘start‘,a,b)
time.sleep(2)
pritn(current_thread().ident,‘end‘)
if __name__ == ‘__main__‘:
p = ThreadPoolExecutor(4)
for i in range(10):
p.submit(func,i,i+1) # 向池中提交任务,和向函数传参
进程池
import time
from threading import current_thread
from concurrent.futures import ProcessPoolExecutor
def func(a,b):
print(current_thread().ident,‘start‘,a,b)
time.sleep(2)
pritn(current_thread().ident,‘end‘)
if __name__ == ‘__main__‘:
p = ProcessPoolExecutor(4)
for i in range(10):
p.submit(func,i,i+1) # 向池中提交任务,和向函数传参
回调函数
import time,random
from threading import current_thread
from concurrent.futures import ThreadPoolExecutor
def func(a,b):
print(current_thread().ident,‘start‘,a,b)
time.sleep(random.randint(1,4))
print(current_thread().ident,‘end‘,a)
return (a,a*b)
def print_func(ret): # 异步阻塞
print(ret.result())
if __name__ == ‘__main__‘:
tp = ThreadPoolExecutor(4)
futrue_l = {}
for i in range(20): # 异步非阻塞的
ret = tp.submit(func,i,b=i+1)
ret.add_done_callback(print_func) # ret这个任务会在执行完毕的瞬间立即触发print_func函数
# 异步阻塞,给对象绑定一个回调函数,可以对结果立即处理,而不是按照顺序结果再处理结果
标签:调度 函数 阻塞 自己的 提升 str ack done 自动
原文地址:https://www.cnblogs.com/tonxin66/p/13123738.html