#!/usr/bin/python3
# -*- coding: utf-8 -*-
import asyncio,time
async def asleep(n):
time.sleep(n) # blocking method
async def doAsync(n):
print("doAsync{} start...".format(n))
await asleep(2) # case 1
#await asyncio.gather(asleep(2)) # case 2
print("doAsync{} end...".format(n))
#...
tasks = [doAsync(i) for i in range(1,4)]
tasks = [asyncio.ensure_future(t) for t in tasks]
if __name__ == "__main__":
loop = asyncio.get_event_loop()
loop.run_until_complete(asyncio.wait(tasks))
loop.close()
输出:
## case 1 output # No concurrency runs
doAsync1 start...
(wait 2 seconds)
doAsync1 end...
doAsync2 start...
(wait 2 seconds)
doAsync2 end...
doAsync3 start...
(wait 2 seconds)
doAsync3 end...
## case 2 output # Concurrency runs
doAsync1 start...
doAsync2 start...
doAsync3 start...
(wait 2*3 seconds)
doAsync1 end...
doAsync2 end...
doAsync3 end...
案例1:
虽然睡着了()也是一个协程,
但是doAsync并未等待#34;等待asleep()"
doAsync不实现并发
案例2:
doAsync是并发的
问题:
答案 0 :(得分:0)
在两种情况下,您提供的代码都不是并发的。这是因为这一行:
async def asleep(n):
time.sleep(n) # blocking method
time.sleep
冻结asyncio事件循环,使其无法处理其他正在运行的同时协同程序。在使用asyncio
时,你永远不应该做这样的事情(如果你想在协同程序中运行一些阻塞代码,你应该使用loop.run_in_executor
在另一个线程中运行它,如图所示here)。
要使代码协程正常工作,您应该使用不阻止事件循环的特殊asyncio版本的sleep:
async def asleep(n):
await asyncio.sleep(n) # blocking method
比较执行此版本(在case1中)与您发布的版本(在case1中):6秒与2秒。
一旦我们使用ensure_future从协同程序创建tasks,这些协同程序就会开始运行:
tasks = [asyncio.ensure_future(c) for c in coros] # this run all coroutines concurently
使用asyncio.gather
- 是另一种运行协同程序的方法:
await asyncio.gather(*coros) # this run all coroutines concurently
方式asyncio
详细工作可能看起来相当复杂。我见过的最好的解释:David Beazley - Python Concurrency From the Ground Up。请注意,您通常不需要了解在练习时使用asyncio
的低级细节。