3.4.3协程

(1)协程: 又称为微线程,用户级线程, 在不开辟线程的基础上可以完成多任务

(2)如何理解协程: 只要在def里面只看到一个yield关键字那么就可以理解为是一个协程

(3)学习协程的目的: 在单线程的基础上完成多任务,多个任务按照一定顺序交替执行

(4)定义、创建、启动协程

import time



# 定义协程

def work1():

    while True:

        print("work1…")

        time.sleep(0.2)

        yield



# 定义协程

def work2():

    while True:

        print("work2…")

        time.sleep(0.2)

        yield



if __name__ == '__main__':

    # 创建协程

    g1 = work1()

    g2 = work2()

    while True:

        # 启动协程

        next(g1)

        next(g2)

(5)greenlet的使用

greenlet是对协程进行了封装,能够让程序员更加清楚地知道协程如何切换执行

      例如:

import greenlet

import time



# 任务1

def work1():

    for i in range(10):

        print("work1...")

        time.sleep(0.2)

        # 切换到协程2执行对应的代码

        g2.switch()



# 任务2

def work2():

    for i in range(10):

        print("work2...")

        time.sleep(0.2)

        # 切换到协程1执行对应的代码

        g1.switch()





if __name__ == '__main__':

    # 创建协程

    g1= greenlet.greenlet(work1)

    # 创建协程

    g2 = greenlet.greenlet(work2)



    # 切换到协程1执行对应的任务

g1.switch()

(6)gevent的使用

import gevent

import time

from gevent import monkey



# 打补丁,让gevent能够识别系统耗时操作,比如:time.sleep,网络请求延时

# 打补丁操作要先执行

monkey.patch_all()



# 任务1

def work1():

    for i in range(10):

        print("work1…")

        time.sleep(0.2)

        #gevent.sleep(0.2)



# 任务2

def work2():

    for i in range(10):

        print("work2…")

        time.sleep(0.2)

        #gevent.sleep(0.2)

if __name__ == '__main__':

    # 创建协程并指派任务

    g1 = gevent.spawn(work1)

    # 创建协程并指派任务

    g2 = gevent.spawn(work2)



    # 主动让线程等待两个协程执行完成以后程序在退出

    g1.join()

    g2.join()

    #也可写成:

    #gevent.joinall([g1, g2])

(7)进程、线程、协程对比

①进程是操作系统资源分配的基本单位

②线程是cpu调度的基本单位,调度那个线程,那个线程执行对应的代码

③多进程开发比单进程多线程开发稳定性要强,但是多进程开发占用的资源更多

④进程之间不共享全局变量,线程之间共享全局变量,提示:多线程共享全局变量要注意资源竞争的问题,解决办法:互斥锁,线程同步

⑤线程之间执行是无序的,协程是按照一定顺序交替执行的

⑥开辟一个协程大概需要5k,开辟一个线程需要512k,开辟进程需要资源是最大的

⑦协程以后的使用场景: 网络爬虫,网络请求

⑧三者之间的关系是:先有进程,进程里面默认提供一个线程,线程里面可以包含多个协程