• 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对象的函数中

    结果:

    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结束。

    结果:  两个函数同时执行。

     上面代码中如果想用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()

    结果:

     接收返回值:

    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)

    结果:  成功打印返回值。

  • 相关阅读:
    [20190415]10g下那些latch是共享的.txt
    [20190415]11g下那些latch是共享的.txt
    [20190409]pre_page_sga=true与连接缓慢的问题.txt
    [20190402]Library Cache mutex.txt
    scrapy简单使用方法
    PHP多进程系列笔(转)
    RdKafka文档翻译
    python判断字符串中是否包含子字符串
    python 逐行读取txt文件
    redis使用watch完成秒杀抢购功能(转)
  • 原文地址:https://www.cnblogs.com/wangdianchao/p/12153258.html
Copyright © 2020-2023  润新知