python_并发编程——协程

1.协程

  1.本质上是一个线程。

  2.能偶在多个任务之间切换来节省一下IO时间。

  3.协程中任务之间的切换也消耗时间,但开销要远远小于进程和线程之间的切换。

真正的协程模块就是使用greenlet来完成多个任务之间的切换。

from greenlet import greenlet


def eat():
    print('eating start')
    g2.switch()  # 切换到g2对象的函数中接着执行,并记录下来当前位置
    print('eating end')
    g2.switch()  # 切换到g2对象的函数中接着执行,并记录下当前位置


def play():
    print('playing start')
    g1.switch()  # 切换到g1对象的函数中接着执行,并记录下当前位置
    print('playing end')


g1 = greenlet(eat)  # 创建对象并将函数注册到对象中
g2 = greenlet(play)  # 创建对象并将函数注册到对象中
g1.switch()  # 切换到g1对象的函数中

结果:python_并发编程——协程

2.协程模块

import gevent


def eat():
    print('eating start')
    gevent.sleep(1)  # gevent感知不到time.sleep,这里暂停要用gevent.sleep
    print('eating end')


def play():
    print('playing start')
    gevent.sleep(1)
    print('playing end')


g1 = gevent.spawn(eat)  # 创建一个协程对象g1,spam括号内第一个参数是函数名,后面可以有多个参数,都是传递给函数的
g2 = gevent.spawn(play)
g1.join()  # 等待g1结束
g2.join()  
# 这里的join可以换城:geven.joinall([g1,g2]),括号内是一个可迭代对象,可以同时等待g1和g2结束。

结果:python_并发编程——协程  两个函数同时执行。

 上面代码中如果想用time.sleep或其他阻塞也可以,但是需要如下操作:

from gevent import monkey  #导入gevent中的monkey模块
import gevent
import time
monkey.patch_all()  # 执行monkey模块中的patch_all方法,就可以使gevent模块识别到time.sleep


def eat():
    print('eating start')
    time.sleep(1)
    print('eating end')


def play():
    print('playing start')
    time.sleep(1)
    print('playing end')


g1 = gevent.spawn(eat)  # 创建一个协程对象g1,spam括号内第一个参数是函数名,后面可以有多个参数,都是传递给函数的
g2 = gevent.spawn(play)
g1.join()  # 等待g1结束
g2.join()

结果:python_并发编程——协程

 接收返回值:

from gevent import monkey  #导入gevent中的monkey模块
import gevent
import time
monkey.patch_all()  # 执行monkey模块中的patch_all方法,就可以使gevent模块识别到time.sleep


def eat():
    print('eating start')
    time.sleep(1)
    print('eating end')
    return 'wdc'


def play():
    print('playing start')
    time.sleep(1)
    print('playing end')
    return 'yhf'


g1 = gevent.spawn(eat)  # 创建一个协程对象g1,spam括号内第一个参数是函数名,后面可以有多个参数,都是传递给函数的
g2 = gevent.spawn(play)
g2.join()  # 等待g1结束
g2.join()
name1 = g1.value  # 接收函数的返回值,需要放在join的后面
name2 = g2.value
print(name1, name2)

结果:python_并发编程——协程  成功打印返回值。