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()
    万般皆下品,唯有读书高!
  • 相关阅读:
    守护进程-锁-队列(生产者消费者模型)
    正则表达式不包含某个字符串写法
    正则表达式匹配不包含某些字符串的技巧
    08.参数估计_点估计
    07.编程理解中心极限定理
    05.编程理解小数和大数定律
    03.描述性统计代码
    02.描述统计 (descriptive statistics)
    oracle之三手工不完全恢复
    oracle之三手工完全恢复
  • 原文地址:https://www.cnblogs.com/s686zhou/p/11363057.html
Copyright © 2011-2022 走看看