zoukankan      html  css  js  c++  java
  • 并发编程---协程

    协程

    协程: 单线程下的并发,应用程序控制的并发,是用户自己调度的,自己控制自己的速度快。

    协程:单线程下的并发,并不是对性能都有所提升,而是监测单线程下的IO行为,遇到IO行为不让原地阻塞,切换到另一个任务执行。

    并发: 切换任务+保存状态

    单线程下实现并发:单线程下的多个任务,遇到IO就切,把单线程整体的IO降到最低。相当于把自己的IO伪装起来,让操作系统将更多的CPU分配给线程。程序用的cpu多,就叫执行效率高

    总结协程特点:

    • 必须在只有一个单线程里实现并发
    • 修改共享数据不需加锁
    • 用户程序里自己保存多个控制流的上下文栈
    • 附加:一个协程遇到IO操作自动切换到其它协程(如何实现检测IO,yield、greenlet都无法实现,就用到了gevent模块(select机制))
    协程

    greenlet模块

    • 再多个任务可以很方便的切,但不能检测到,遇到IO 切
    • 比yield 好,但是还是不好,遇到io不会切
    from greenlet import greenlet
    import time
    
    def eat(name):
        print('%s eat1' %name)
        # time.sleep(10) 遇到IO不会切
        g2.switch('yang')
        print('%s eat2' %name)
        g2.switch()
    
    def play(name):
        print('%s play1' %name)
        g1.switch()
        print('%s play2' %name)
    
    g1 = greenlet(eat)
    g2 = greenlet(play)
    
    g1.switch('yang') #第一次启动需要传参数
    '''
    打印结果:
    yang eat1
    yang play1
    yang eat2
    yang play2
    '''
    greenlet模块

    gevent模块

    gevent: 里面封装了greenlet模块,但是可以检测到IO操作,自动切换任务

    缺点:只能检测到gevent.sleep()等,gevent的IO阻塞

    解决方法:导入gevent模块下的monkey方法,在文件的开头写:from gevent import monkey;monkey.patch_all()

    from gevent import monkey;monkey.patch_all()
    import gevent
    import time
    
    def eat(name):
        print('%s eat1' %name)
        gevent.sleep(3)
        print('%s eat2' %name)
    
    
    def play(name):
        print('%s play1' %name)
        gevent.sleep(4)
        print('%s play2' %name)
    
    start_time = time.time()
    g1 = gevent.spawn(eat,'yang')
    g2 = gevent.spawn(play,'hang')
    
    g1.join()
    g2.join()
    stop_time = time.time()
    print(stop_time-start_time)
    '''
    打印结果:
    yang eat1
    hang play1
    yang eat2
    hang play2
    4.004916191101074
    gevent换成time的话:
    执行时间就变成7秒多
    '''
    
    from gevent import monkey;monkey.patch_all()
    import gevent
    import time
    
    def eat(name):
        print('%s eat1' %name)
        gevent.sleep(3)
        print('%s eat2' %name)
    
    
    def play(name):
        print('%s play1' %name)
        gevent.sleep(4)
        print('%s play2' %name)
    
    g1 = gevent.spawn(eat,'yang')
    g2 = gevent.spawn(play,'hang')
    
    # g1.join() # 等到g1执行完
    # g2.join() # 等到g2执行完
    
    gevent.joinall([g1,g2 ]) # 等到g1和g2都执行完
    g1.join()
    g2.join()
    
    """
    打印结果:
    egon eat 1 
    alex play 1 
    egon eat 2 
    alex play 2  
    """
    gevent模块

    gevent模块下的套接字通信

    #基于gevent实现
    import socket
    from gevent import monkey,spawn;monkey.patch_all()
    
    def communicate(conn):
        while True:
            try:
                data = conn.recv(1024)
                if not data:break
                conn.send(data.upper())
            except ConnectionResetError:
                break
        conn.close()
    
    def server(ip,port):
        server = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
        server.bind((ip,port))
        server.listen(5)
    
        while True:
            conn, addr = server.accept()
            spawn(communicate,conn)
    
        server.close()
    
    if __name__ == '__main__':
        g = spawn(server,'127.0.0.1',8090)
        g.join()
    服务端
    import socket
    from threading import Thread,currentThread
    
    def client():
        client = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
        client.connect(('127.0.0.1',8090))
    
        while True:
            client.send(('%s hello' %currentThread().getName()).encode('utf-8'))
            data = client.recv(1024)
            print(data.decode('utf-8'))
        client.close()
    
    if __name__ == '__main__':
        for i in range(500): # 500个客户端同时登陆,服务端一个线程就可以接收500个client
            t = Thread(target=client)
            t.start()
    # 单线程的IO降下来,会大大提高程序的效率
    客户端
  • 相关阅读:
    OnMeasureItem和OnDrawItem的区别和联系
    DockPanel 类
    C# 源码 AForge.NET
    ystem.Windows.Forms.SplitContainer : ContainerControl, ISupportInitialize
    System.Windows.Forms.Control : Component, IOleControl, IOleObject, IOleInPlaceObject, IOleInPlaceActiveObject....
    System.ComponentModel.Component : MarshalByRefObject, IComponent, IDisposable
    System.Windows.Forms.ListView : Control
    vs2013 密钥_
    系统封装 EasyBoot如何将WIN7安装版提取到光盘
    系统封装 ES3使用方法
  • 原文地址:https://www.cnblogs.com/Mryang123/p/8928987.html
Copyright © 2011-2022 走看看