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

    协程 (单线程下实现并发)

      进程:资源单位

      线程:执行单位

      协程:单线程下实现并发

    并发:切换+保存状态

    程序员自己通过代码自己检测程序中的IO

    一旦遇到了IO自己通过代码切换

    给操作系统的感觉就是你这个线程没有任何的IO    从而提升代码的运行效率

    切换+保存状态一定能够提升效率吗?

      1.当任务是IO密集型的情况下     提升效率

         2.当任务是计算密集型的情况下    降低效率

    接下来 我们进行验证  

    1.在计算密集型的情况下,通过切换+保存状态   效率到底是降低了还是提升了呢?

    这是串行执行的时间:

    # 串行执行 0.8540799617767334
    import time
    
    def func1():
        for i in range(10000000):
            i+1
    
    def func2():
        for i in range(10000000):
            i+1
    
    start = time.time()
    func1()
    func2()
    stop = time.time()
    print(stop - start)

    下面是切换+保存状态的执行时间:

    #基于yield并发执行  1.3952205181121826
    import time
    def func1():
        while True:
            10000000+1
            yield
    
    def func2():
        g=func1()
        for i in range(10000000):
            time.sleep(100)  # 模拟IO,yield并不会捕捉到并自动切换
            i+1
            next(g)
    
    start=time.time()
    func2()
    stop=time.time()
    print(stop-start)

    根据执行时间来看  明显效率是降低了

    2.在IO密集型的情况下,通过切换+保存状态   效率到底是降低了还是提升了呢?

    首先我们需要找到一个能够识别IO的工具,遇到IO就可以自动的切换

    这里我们就用到了gevent模块

    这是串行的执行结果:

    from gevent import monkey;monkey.patch_all()
    from gevent import spawn
    import  time
    
    '''
    注意  gevent模块没办法自动识别 time.sleep 等io情况
    需要你手动配置一个参数
    '''
    
    def heng():
        print('哼!')
        time.sleep(2)
        print('哼!')
    
    def ha():
        print('哈!')
        time.sleep(3)
        print('哈!')
    
    start = time.time()
    
    heng()
    ha()
    
    print(time.time()-start)
    #5.041796445846558

    下面是通过切换+保存状态来执行  利用gevent模块

    from gevent import monkey;monkey.patch_all()
    from gevent import spawn
    import  time
    
    '''
    注意  gevent模块没办法自动识别 time.sleep 等io情况
    需要你手动配置一个参数
    '''
    
    def heng():
        print('哼!')
        time.sleep(2)
        print('哼!')
    
    def ha():
        print('哈!')
        time.sleep(3)
        print('哈!')
    
    start = time.time()
    
    g= spawn(heng)
    g1 = spawn(ha)
    g.join()
    g1.join()
    
    print(time.time()-start)
    
    #3.041301727294922

    明显的看出在IO密集型的情况下  切换+保存状态能够提升效率

    Gevent应用举例 

    利用协程实现并发

    实现TCP服务端的并发

    server端

    import socket
    from gevent import monkey;monkey.patch_all()
    from gevent import spawn
    
    sk = socket.socket()
    sk.bind(('127.0.0.1', 8080))
    sk.listen()
    def talk(conn):
        while True:
            try:
                data = conn.recv(1024)
                if len(data) == 0 :break
                print(data.decode('utf-8'))
                conn.send(b'hi')
            except ConnectionResetError as e:
                print(e)
                break
        conn.close()
    
    def server():
        while True:
            conn,addr = sk.accept()
            spawn(talk,conn)
    
    if __name__ == '__main__':
        res = spawn(server)
        res.join()

    client端 起了400个线程

    from threading import Thread
    import socket
    
    def client():
        sk = socket.socket()
        sk.connect(('127.0.0.1',8080))
    
    
        while True:
            sk.send(b'hello')
            data = sk.recv(1024).decode('utf-8')
            print(data)
    
    for i in range(400):
        t = Thread(target=client)
        t.start()
    万般皆下品,唯有读书高!
  • 相关阅读:
    检索 COM 类工厂中 CLSID 为 {00024500-0000-0000-C000-000000000046} 的组件失败的解决方案--报错80080005
    c# 数组拼接、DataTable拼接
    【C#】数据类型(sbyte,byte,short,ushort,int,uint,long,ulong和char。、、、)
    一个字符占几个字节
    js获取不到scrollTop值的问题
    省市县2020年最新更新
    【警惕流文件转string存数据库操作】记一次数据库异常增长的排查经历
    【VS Code】利用Live Server插件搭建本地服务
    数据库中float类型存储时位数增多问题
    【小工具】阿里云视频上传工具
  • 原文地址:https://www.cnblogs.com/s686zhou/p/11363057.html
Copyright © 2011-2022 走看看