1. 说明:

线程的缺点:在Python解释器中有一个GIL锁 — Global Interpreter Lock,在Python中的线程执行前都会获得这个GIL锁,每次执行100条字节码后,解释器就自动释放这个GIL锁,让别的线程有机会执行。Python会把所有的线程都加上这把锁,然后多线程之间只能交替执行,并未实现真正的并发执行。
使用协程可以避免,相当于异步编程
async关键字用于定义异步函数
await关键字用于等待异步函数执行(可等待对象包括:协程对象,Task对象,Future对象)

2. 简单使用:

# 引入协程包
import asyncio
import time

def demoAsync():
    # 使用async修饰普通函数,可将普通函数变成异步函数
    async def task1():
        print("Execute the first task...")
        # 耗时操作使用await修饰,这样会随机进入下一个协程函数执行
        await asyncio.sleep(3)
        print("the first task is done....")

    async def task2():
        print("Execute the second task...")
        await asyncio.sleep(3)
        print("the second task is done...")

    async def task3():
        print("Execute the third task...")
        await asyncio.sleep(3)
        print("the third task is done...")

    # 创建任务事件循环
    loop = asyncio.get_event_loop()
    # 将异步任务加入到一个列表中,形成任务列表
    tasks = [task1(), task2(), task3()]
    # 开始任务事件循环,直到最后一个任务执行结束
    loop.run_until_complete(asyncio.wait(tasks))
    # 最后一个任务执行结束后,关闭循环
    loop.close()


def demoNormal():
    def task1():
        print("Execute the first task...")
        # 耗时操作使用await修饰,这样会随机进入下一个协程函数执行
        time.sleep(3)
        print("the first task is done....")

    def task2():
        print("Execute the second task...")
        time.sleep(3)
        print("the second task is done...")

    def task3():
        print("Execute the third task...")
        time.sleep(3)
        print("the third task is done...")

    task1()
    task2()
    task3()


if __name__ == '__main__':
    startAsync = time.time()
    demoAsync()
    endAsync = time.time()
    # 用了异步执行,大概使用3s左右的时间  Async Time:3.0043070316314697
    print(str("Async Time:" + str(endAsync - startAsync)))

    startNormal = time.time()
    demoNormal()
    endNormal = time.time()
    # 不用异步,则打印出来的时间应该时9s左右  Normal time:9.009456157684326
    print(str("Normal time:" + str(endNormal - startNormal)))

3. Task对象:

Tasks用于并发调度协程,通过asyncio.create_task(协程对象)的方式创建Task对象,这样可以让协程加入事件循环中等待被调度执行,此函数一次只能添加一个协程任务到事件循环种,使用**asyncio.gather(协程对象1,协程对象2,…)**可以一次加入多个协程任务到事件循环种。
注意:asyncio.create_task() 函数在 Python 3.7 中被加入,本质上是将协程对象封装成task对象,并将协程立即加入事件循环,同时追踪协程的状态。

import asyncio


async def func():
    print(1)
    await asyncio.sleep(2)
    print(2)
    return "返回值"


async def main():
    print("main开始")

    # 创建协程,将协程函数加入到事件循环中,处于就绪状态,还未执行。
    task1 = asyncio.create_task(func())

    # 使用 gather 函数可以一次性将多个协程函数加入事件循环中。
    task2 = asyncio.gather(func(), func(), func())

    print("main结束")

    # 当执行某协程遇到IO操作时,会自动化切换执行其他任务。
    # 此处的await是等待相对应的协程全都执行完毕并获取结果
    ret1 = await task1  # task1 执行完之后,再执行下面的代码
    ret2 = await task2

    print(ret1, ret2)


asyncio.run(main())	# 使用run()方法启动协程任务执行,在python3.7的版本能够使用这种方式

持续更新中,请大家多多关注…