协程

90 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第11天,点击查看活动详情

协程:协助线程的工具。又称纤程。协程的作用在执行的任务A之后可以随时的切换到任务B进行执行,而不需要进行多线程之间的切换。可以提高效率(因为,减少了多线程开闭的资源开销),因为只在一个线程中,不存在同时对数据进行更新,在协程中资源共享是不需要加锁的。

协程在一个线程的情况下交替的执行多个任务。

import time

def func_A():
    while True:
        yield '-------------任务一执行------------'
        time.sleep(1)

def func_B():
    while True:
        yield '-------------任务二执行------------'
        time.sleep(1)

def main():
    A = func_A()
    B = func_B()
    while True:
        print(next(A))
        print(next(B))

main()

模块的下载

pip install greenlet
pip install gevent

# 镜像
阿里云 http://mirrors.aliyun.com/pypi/simple/

中国科技大学 https://pypi.mirrors.ustc.edu.cn/simple/

豆瓣(douban) http://pypi.douban.com/simple/

清华大学 https://pypi.tuna.tsinghua.edu.cn/simple/

中国科学技术大学 http://pypi.mirrors.ustc.edu.cn/simple/


pip install 模块名 -i http://mirrors.aliyun.com/pypi/simple/

greenlet的使用

该模块可以使两个任务之间的切换的比较简便一点

greenlet实现了协程之间任务切换 , 但是任务之间的切换需要手动的设置

import greenlet
import time

def func_A():
    while True:
        print('-------------任务一执行------------')
        time.sleep(1)
        B.switch()

def func_B():
    while True:
        print('-------------任务二执行------------')
        time.sleep(1)
        A.switch()

if __name__ == '__main__':
    # 创建协程对象
    A = greenlet.greenlet(func_A)
    B = greenlet.greenlet(func_B)
    # 启动协程(同时也是对协程任务的切换)
    A.switch()
from greenlet import greenlet

def eat(name):
    print(f'{name}在吃饭')
    s.switch('张三')
    print(f'{name}还在吃饭')
    s.switch()

def sleep(name):
    print(f'{name}在睡觉')
    e.switch()
    print(f'{name}还在睡觉')


if __name__ == '__main__':
    e = greenlet(eat)
    s = greenlet(sleep)
    # 协程参数 ,只写在第一个启动协程的地方
    e.switch('阿宸')

gevent的使用

当程序遇到IO阻塞的情况下会自动的切换协程任务

import gevent

def eat(name):
    print(f'{name}在吃饭')
    gevent.sleep(2)
    print(f'{name}还在吃饭')


def sleep(name):
    print(f'{name}在睡觉')
    gevent.sleep(4)
    print(f'{name}还在睡觉')


if __name__ == '__main__':

    e = gevent.spawn(eat , '阿宸')
    s = gevent.spawn(sleep , 'Tom')
    e.join()
    s.join()
from gevent import monkey
import gevent
import time

# 给程序打上补丁,让gevent可以识别所有的io阻塞都进行打上标记
monkey.patch_all()

def eat(name):
    print(f'{name}在吃饭')
    time.sleep(2)
    print(f'{name}还在吃饭')


def sleep(name):
    print(f'{name}在睡觉')
    time.sleep(4)
    print(f'{name}还在睡觉')


if __name__ == '__main__':
    start = time.time()
    e = gevent.spawn(eat , '阿宸')
    s = gevent.spawn(sleep , 'Tom')
    e.join()
    s.join()
    print(f'结束时间{time.time() - start}')

进程、线程、协程

进程:最小的资源分配单位 , 开辟多进程就会占用过多资源。

线程:操作系统的调度单位 , 线程占用的资源比进程少,线程的资源只有进程分配

协程:执行切换任务,因为需要进行任务切换,比较杂比较碎片化,不占用资源

比如任务数量只有5-6个:可以只开辟一个线程 + 协程

多任务:多线程+协程