zoukankan      html  css  js  c++  java
  • 协程回顾

    在这里插入图片描述
    Python通过yield提供了对协程的基本支持,但是不完全。而第三方的gevent为Python提供了比较完善的协程支持。

    gevent是第三方库,通过greenlet实现协程,其基本思想是:

    当一个greenlet遇到IO操作时,比如访问网络,就自动切换到其他的greenlet,等到IO操作完成,再在适当的时候切换回来继续执行。由于IO操作非常耗时,经常使程序处于等待状态,有了gevent为我们自动切换协程,就保证总有greenlet在运行,而不是等待IO

    生成器send方式:

    def create_num(all_num):
        a,b = 0,1
        current_num = 0
        while current_num < all_num:
            ret = yield a
            print(ret)
            a,b = b, a+b
            current_num +=1
    
    obj = create_num(10)
    ret= next(obj)
    print(ret)
    ret = obj.send('鲁班七号')
    print(ret)
    >>>
    0
    鲁班七号
    1
    

    yield完成多任务

    import time
    def task1():
        while True:
            print("task one")
            time.sleep(1)
            yield
    def task2():
        while True:
            print("task 2")
            time.sleep(1)
            yield
    
    def main():
        obj1 =  task1()
        obj2 = task2()
        while True:
           next(obj1)
           next(obj2)
    if __name__ == '__main__':
        main()
    >>>
    task one
    task 2
    task one
    task 2
    task one
    ......
    

    使用greenlet完成多任务

    from greenlet import greenlet
    import time
    
    def f1():
        while True:
            print('-----A-----')
            gr2.switch()
            time.sleep(0.5)
    
    def f2():
        while True:
            print('-----B-----')
            gr1.switch()
            time.sleep(0.5)
    if __name__ == '__main__':
        gr1 = greenlet(f1)
        gr2 = greenlet(f2)
        gr1.switch()
    

    gevent

    import gevent
    import time
    
    def f1(n):
        for i in range(n):
            print(gevent.getcurrent(),i)
            gevent.sleep(1) #模拟一个耗时操作,模拟耗时操作要用gevent里面函数
    
    def f2(n):
        for i in range(n):
            print(gevent.getcurrent(),i)
            gevent.sleep(1)
    
    if __name__ == '__main__':
         g1 = gevent.spawn(f1,5)
         g2 = gevent.spawn(f2,5)
         g1.join()
         g2.join()
    >>>
    <Greenlet at 0x2f598b0: f1(3)> 0
    <Greenlet at 0x2f599c0: f2(3)> 0
    <Greenlet at 0x2f598b0: f1(3)> 1
    <Greenlet at 0x2f599c0: f2(3)> 1
    <Greenlet at 0x2f598b0: f1(3)> 2
    <Greenlet at 0x2f599c0: f2(3)> 2
    

    打补丁:不替换sleep, socket.conn,socket.reciv...

    由于切换是在IO操作时自动完成,所以gevent需要修改Python自带的一些标准库,这一过程在启动时通过monkey patch完成

    from gevent import monkey
    
    #打补丁,保证不用替换原来耗时操作的函数
    monkey.patch_all()
    

    join_all方法:

        gevent.joinall([
            gevent.spawn(f1, 5),
            gevent.spawn(f2, 5)
        ])
    
    
    #encoding:utf-8
    # __author__ = 'donghao'
    # __time__ = 2019/4/2 13:57
    import gevent
    import time
    from gevent import monkey
    
    #打补丁,保证不用替换原来耗时操作的函数
    monkey.patch_all()
    
    def f1(n):
        for i in range(n):
            print(gevent.getcurrent(),i)
            time.sleep(1)
    
    def f2(n):
        for i in range(n):
            print(gevent.getcurrent(),i)
            time.sleep(1)
    
    if __name__ == '__main__':
        gevent.joinall([
            gevent.spawn(f1, 5),
            gevent.spawn(f2, 5)
        ])
        # 相当于:
         # g1 = gevent.spawn(f1,5)
        # g2 = gevent.spawn(f2,5)
        # g1.join()
        # g2.join()  
        print('end of main')
    >>>
    <Greenlet at 0x39fc2d8: f1(5)> 0
    <Greenlet at 0x39fc360: f2(5)> 0
    <Greenlet at 0x39fc2d8: f1(5)> 1
    <Greenlet at 0x39fc360: f2(5)> 1
    <Greenlet at 0x39fc2d8: f1(5)> 2
    <Greenlet at 0x39fc360: f2(5)> 2
    <Greenlet at 0x39fc2d8: f1(5)> 3
    <Greenlet at 0x39fc360: f2(5)> 3
    <Greenlet at 0x39fc2d8: f1(5)> 4
    <Greenlet at 0x39fc360: f2(5)> 4
    end of main
    

    由于gevent是基于IO切换的协程,所以最神奇的是,我们编写的Web App代码,不需要引入gevent的包,也不需要改任何代码,仅仅在部署的时候,用一个支持geventWSGI服务器,立刻就获得了数倍的性能提升

  • 相关阅读:
    Java8 新特性default
    Java Map操作
    Java List操作
    Java Set操作
    Java集合 List,Set,Map
    Java final,static 关键字
    Java ConcurrentHashMap
    Java Synchronized的用法
    Linux 基本收集
    HashMap 扩容 加载因子
  • 原文地址:https://www.cnblogs.com/donghaoblogs/p/10642567.html
Copyright © 2011-2022 走看看