1. 使用异步sleep的情形。
import asyncio
import time
from datetime import datetime
async def aa(count):
print("--child process begin ---",datetime.now(),count)
await asyncio.sleep(1)
#time.sleep(2)
print("--child process ends ---",datetime.now(),count)
async def me():
tasks = []
N = 4
for count in range(12):
if count % N == N-1:
for idx in range(N-1,-1,-1):
tasks.append(asyncio.create_task(aa(count-idx)))
print("88888888888888888888888888888")
for task in tasks:
await task
print(tasks)
tasks = []
print("-------------------",count,"--------------------")
if __name__ == "__main__":
asyncio.run(me())
执行结果(部分):
可以看到,4个子进程确实是近乎同时开始的,并且结束时间都延迟了1秒钟(asyncio.sleep(1) )。符合预期。
2. 子进程中存在阻塞代码。
在子进程中使用time.sleep() 代表阻塞代码。
执行结果为:
可以看到,虽然开启了多个子进程,但子进程之间是串行关系,一个子进程结束后,另外一个子进程才能开始。这表明,如果进程中存在阻塞代码,就会失去异步/多任务的优势。从目前看,这个结论看起来是没有问题的。暂存无论。接着看。
3. 在子进程中加入await
执行结果:
可以看大, 加入await 语句后,子进程又可以并发了。
基于以上代码和结果,async 需要和await 配对使用,单独使用虽然不会报错,但代码变成了串行。await 使得子进程会将控制权交回给事件循环,允许另外一个协程得以执行。如果没有await,则除非子进程执行完毕,其他子进程无法执行,这就解释了为什么第二种没有await时,子进程变成了串行执行。
另外还有一个问题:虽然子进程时近乎同时开始,但执行结束的时间确实串行的,又好像是进入了串行模式,一个执行结束另外一个才能得以执行。
4. time.sleep 是明显的阻塞语句,一般情况下能够立即返回的都不是阻塞语句,比如创建一个数据库连接,创建网络连接等都可以在协程中正确执行。
执行结果:
可以看到,4个子进程是近乎同时开始和同时结束的,这样就实现了多个子进程并发执行任务。