day10-协程遇到IO操作自动切换

产生的问题

前面介绍了greenlet实现了协程,但是在遇到I/O操作时,还没实现自动切换,下面可以通过gevent模块实现该功能。

gevent的好处在于可以自动切换协程,一般来说I/O操作比较耗时,那么当一个协程在等待I/O时,它会自动切换到其他协程工作,这样就能够充分利用CPU了。

概述

Gevent 是一个第三方库,可以轻松通过gevent实现并发同步或异步编程,在gevent中用到的主要模式是Greenlet, 它是以C扩展模块形式接入Python的轻量级协程。 Greenlet全部运行在主程序操作系统进程的内部,但它们被协作式地调度。

常用函数

  • gevent.spawn(func, args, *kwargs) :创建greenlet对象

  • gevent.joinall(greenlets) :传入一个greenlet对象列表,开始所有任务并等待完成

  • gevent.sleep(seconds) :挂起secodes秒

  • gevent.kill / killall:杀死某个greenlet或一个list的greenlet

  • gevent.wait(objects=None, timeout=None, count=None):进入等待

gevent

安装gevent

bogon:module_4 huwei$ pip3 install gevent
Collecting gevent
  Downloading gevent-1.2.2-cp35-cp35m-macosx_10_6_intel.whl (1.1MB)
    100% |████████████████████████████████| 1.1MB 220kB/s
import gevent


def func1():
    print('Running in func1') #1
    gevent.sleep(2) #模拟一遇到I/O就切换 #2 
    print('Explicit context switch to func1 again') (#7) #10


def func2():
    print('Explicit context to func2') #3
    gevent.sleep(1) #模拟一遇到I/O就切换 #4
    print('Implicit context switch back to func2 ') #8

def func3():
    print('Running in func3') #5
    gevent.sleep(1) #模拟一遇到I/O就切换 #6
    print('Running in func3 again') #9


gevent.joinall([
    gevent.spawn(func1),
    gevent.spawn(func2),
    gevent.spawn(func3),
]) #生成协程

#运行输出

Running in func1
Explicit context to func2
Running in func3
Implicit context switch back to func2 
Running in func3 again
Explicit context switch to func1 again

Process finished with exit code 0

执行过程解析:当#1执行遇到#2时切换到#3执行遇到#4切换到#5执行遇到#6切换到#7执行发现sleep(2)还没有执行完毕,所以又切换到#8执行完到执行完#9,又切回到#10,执行完毕。

程序小结

  • 整个程序在一遇到I/O就切换,但是整个程序是并行的,所以运行只需要2s,如果是串行的就需要4s。
  • 如果程序有50处I/O,每个I/O花2s的话,运行整个程序,那么如果是串行就需要100s,如果是协程的话,就是2s。
posted @ 2017-12-14 16:51  Mr.hu  阅读(268)  评论(0编辑  收藏  举报