• (20)gevent协程


    协程: 也叫纤程,协程是线程的一种实现,指的是一条线程能够在多任务之间来回切换的一

    种实现,对于CPU、操作系统来说,协程并不存在

    任务之间的切换会花费时间.目前电脑配置一般线程开到200会阻塞卡顿 .

    协程的实现: 协程帮助你记住哪个任务执行到哪个位置上了,并且实现安全的切换

    一个任务一旦阻塞卡顿,立刻切换到另一个任务继续执行,保证线程总是忙碌的,更加充

    分的利用,

    CPU,抢占更多的时间片

    一个线程可以由多个协程来实现,协程之间不会产生数据安全问题

    协程模块:

    greenlet gevent的底层,协程,切换的模块

    gevent 直接用的,gevent能提供更全面的功能

    (1) 用生成器写生产者消费者模型

    # producer 生产者
    def producer():
        for i in range(10):
            yield i
    # consumer 消费者
    def consumer():
        g = producer()
        for num in g:
            print(num)
    consumer()
    View Code

    执行结果:

    0
    1
    2
    3
    4
    5
    6
    7
    8
    9
    View Code

    (2) 普通版 greenlet+switch组合 基本实现,只能用switch进行手动切换,

    缺陷:不能规避雕io,不能自动实现遇到阻塞就切换.

    from greenlet import greenlet
    import time
    def eat():
        print("eat one1")
        # 切换到play这个协程中
        g2.switch()
        time.sleep(1)
        print("eat one2")
    def play():
        print("play one1")
        print("play one2")
        g1.switch()
    g1 = greenlet(eat)
    g2 = greenlet(play)
    g1.switch()
    View Code

    执行结果

    eat one1
    play one1
    play one2
    eat one2
    View Code

    (3) 升级版 gevent+spawn组合 有缺陷,不能够识别time.sleep()

    spawn 自动检测阻塞,遇到阻塞就切换,相当于switch 的升级版 

    import gevent,time
    def eat():
        print("eat one1")
        time.sleep(1)
        print("eat one2")
    def play():
        print("play one1")
        time.sleep(1)
        print("play one2")
    g1 = gevent.spawn(eat)
    g2 = gevent.spawn(play)
    # 协程的阻塞也是join
    g1.join()  # 阻塞直到g1协程执行完毕
    g2.join()  # 阻塞直到g2协程执行完毕
    View Code

    执行结果:发现者并不是我们我们希望的结果

    eat one1
    eat one2
    play one1
    play one2
    View Code

    (4) 进阶版本 用gevent.sleep() 取代time.sleep()

    import gevent
    def eat():
        print("eat one1")
        gevent.sleep(1)
        print("eat one2")
    def play():
        print("play one1")
        gevent.sleep(1)
        print("play one2")
    g1 = gevent.spawn(eat)
    g2 = gevent.spawn(play)
    # 协程的阻塞也是join
    g1.join()  # 阻塞直到g1协程执行完毕
    g2.join()  # 阻塞直到g2协程执行完毕
    View Code

    执行结果:问题是解决了,但是看起来怪怪的,改变了原有的time,sleep()语法

    eat one1
    play one1
    eat one2
    play one2
    View Code

    (5) 终极解决办法 gevent+spawn +monkey.patch_all()

    from gevent import monkey;monkey.patch_all()
    import time,gevent
    def eat():
        print("eat one1")
        time.sleep(1)
        print("eat one2")
    def play():
        print("play one1")
        time.sleep(1)
        print("play one2")
    g1 = gevent.spawn(eat)
    g2 = gevent.spawn(play)
    # 协程的阻塞也是join
    g1.join()  # 阻塞直到g1协程执行完毕
    g2.join()  # 阻塞直到g2协程执行完毕
    View Code

    执行结果:perfect 完美!你没有看错,就是这只猴子,老厉害了,解决了所有问题

    eat one1
    play one1
    eat one2
    play one2
    View Code

    .

     

     

  • 相关阅读:
    Objective-C面向对象-对象和类
    eImage(仅两行代码实现输出从数据库中查询到的二进制字段)标签
    yii第三方插件snoopy配置
    iOS应用崩溃日志分析 iOS应用崩溃日志揭秘
    斯坦福《机器学习》Lesson6感想———1、函数间隔和几何间隔
    openstack 中国联盟公开课參会总结
    【翻译自mos文章】多租户中的service管理
    谷歌浏览器訪问不了啦,oh shit!
    从程序员转向淘宝店主的探索
    Python爬取韩寒所有新浪博客
  • 原文地址:https://www.cnblogs.com/lyj910313/p/10787411.html
Copyright © 2020-2023  润新知