Python异步编程

同步与异步 & 阻塞与非阻塞

前两者与后两者并没有一一对应的关系,即同步不一定是阻塞的,也可能是非阻塞的(当让这样做意义不大),同样异步可以是阻塞的也可以是非阻塞的。

同步与异步

同步与异步关注的是消息通讯机制。

同步

在发出一个调用时,如果没有得到返回结果则该调用就不会返回。也因此,同步的条件下只要返回便可以得到返回值。

异步

在发出一个调用时,该调用直接返回,正因如此并不会立刻得到调用结果。最终的调用值由被调用者通过状态、通知来通知调用者,或者通过回调函数处理。

阻塞与非阻塞

阻塞与非阻塞关注的是程序在等待调用结果时的状态。

阻塞

阻塞指的是在调用结果为返回之前,当前线程会被挂起,直等到返回调用结果。

非阻塞

非阻塞指的是未得到调用结果时线程不会被挂起、阻塞。

  • 异步时调用得到返回值时会主动通知主程序。
  • 同步时需要主程序不断检查调用是否得到了返回结果。

举例

出场人物:老张,水壶两把(普通水壶,简称水壶;会响的水壶,简称响水壶)。

  1. 老张把水壶放到火上,立等水开。(同步阻塞)老张觉得自己有点傻
  2. 老张把水壶放到火上,去客厅看电视,时不时去厨房看看水开没有。(同步非阻塞)老张还是觉得自己有点傻,于是变高端了,买了把会响笛的那种水壶。水开之后,能大声发出嘀~~~~的噪音。
  3. 老张把响水壶放到火上,立等水开。(异步阻塞)老张觉得这样傻等意义不大
  4. 老张把响水壶放到火上,去客厅看电视,水壶响之前不再去看它了,响了再去拿壶。(异步非阻塞)老张觉得自己聪明了。

简单使用

async def用来定义异步函数,其内部有异步操作。每个线程有一个事件循环,主线程调用asyncio.get_event_loop()时会创建事件循环,把异步的任务丢给这个循环的run_until_complete()方法,事件循环会安排协同程序的执行。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import asyncio
import time
import concurrent.futures as cf

def myfun(i):
print('start {}th'.format(i))
time.sleep(1)
print('finsh {}th'.format(i))

async def main():
with cf.ThreadPoolExecutor(max_workers=10) as executor:
loop = asyncio.get_event_loop()
futures = (loop.run_in_executor(executor, myfun, i) for i in range(10))
for result in await asyncio.gather(*futures):
pass

loop = asyncio.get_event_loop()
loop.run_until_complete(main())

(未完待续………..

本文标题:Python异步编程

文章作者:Darren

发布时间:2018年12月22日 - 16:12

最后更新:2018年12月23日 - 17:12

原始链接:http://Darren2017.github.io/2018/12/22/Python异步编程/

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。