zoukankan      html  css  js  c++  java
  • 进程池线程池与同步异步阻塞非阻塞

    一、进程池线程池(*****)

    无论是开进程还是开线程都消耗资源,开线程比开进程消耗的资源要小

    1、池:为了减缓计算机硬件的压力,避免计算机硬件设备崩溃。虽然减轻了计算机的压力,但是一定程度上降低了持续的效率

    2、为什么要用“池”: 池子使用来限制并发的任务数目,限制我们的计算机在一个自己可承受的范围内去并发地执行任务

    3、进程池线程池:为了限制开设的进程数和线程数,从而保证计算机硬件的安全

    4、池子内什么时候装进程:并发的任务属于计算密集型

    池子内什么时候装线程:并发的任务属于IO密集型

    ①进程池

    from concurrent.futures import ProcessPoolExecutor
    import time, os, random
    
    def task(x):
        print('%s 接客' % os.getpid())
        time.sleep(random.randint(2, 5))
        return x**2
    
    if __name__ == '__main__':
        p = ProcessPoolExecutor(5)   # ()内不加参数默认开启的进程数是cpu的核数
        for i in range(20):
            p.submit(task, i)

    ②线程池

    from concurrent.futures import  ThreadPoolExecutor
    import time,random
    
    def task(x):
        print('%s 接客' % x)
        time.sleep(random.randint(2, 5))
        return x ** 2
    
    if __name__ == '__main__':
        p = ThreadPoolExecutor(4)  # ()内不加参数默认开启的线程数是cpu的核数*5
        for i in range(20):
            p.submit(task, i)

    二、同步异步阻塞非阻塞(*****)

    1、同步与异步:提交任务的两种方式

    同步调用:提交完任务后,就在原地等待,直到任务运行完毕后,拿到任务的返回值,才继续执行下一行代码

    异步调用:提交完任务后,不在原地等待,直接执行下一行代码

    from concurrent.futures import ThreadPoolExecutor
    import time, random
    
    def task(x):
        print('%s 接客' % x)
        time.sleep(random.randint(1, 3))
        return x ** 2
    
    # 异步调用
    if __name__ == '__main__':
        p = ThreadPoolExecutor(4)  # 默认开启的线程数是cpu的核数*5
        obj_l = []
        for i in range(10):
            obj = p.submit(task, i)
            obj_l.append(obj)
        p.shutdown(wait=True)      # 等待所有任务运行完毕在执行结果obj调result(),这里拿结果不同等待
        print(obj_l[0].result())
        print('')
    
    
    # 同步调用
    if __name__ == '__main__':
        p = ThreadPoolExecutor(4)  # 默认开启的线程数是cpu的核数*5
        for i in range(10):
            res = p.submit(task, i).result()    # 提交任务在原地等结果,与阻塞没有关系。
                                                # 拿到结果之后再继续执行
            print(res)
        print('')

    2、阻塞与非阻塞:程序的两种运行状态 

    阻塞:遇到IO就发生阻塞,程序一旦遇到阻塞操作就会停在原地,并且立刻释放CPU资源

    非阻塞(就绪态或运行态):没有遇到IO操作,或者通过某种手段让程序即便是遇到IO操作也不会停在原地执行其他操作,力求尽可能多的占有CPU

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

    1、并发实现的本质:切换+保存状态

    2、并发:看起来是同时运行,切换+保存状态

      并行:真正意义上的同时运行,只有在多cpu的情况下才能 实现并行,4个cpu能够并行4个任务

      串行:一个人完完整整地执行完毕才运行下一个任务

      协程:单线程下实现并发,自己通过代码层面监测自己的io行为, 并自己实现切换+保存状态,让操作系统误认为这个线程没有io

     ①客户端

    from threading import Thread, current_thread
    import socket
    
    def client():
        client = socket.socket()
        client.connect(('127.0.0.1', 8080))
        n = 1
        while True:
            data = '%s %s' % (current_thread().name, n)
            n += 1
            client.send(data.encode('utf-8'))
            info = client.recv(1024)
            print(info)
    
    if __name__ == '__main__':
        for i in range(100):
            t = Thread(target=client)
            t.start()

    ②服务端

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

    四、gevent模块使用

    from gevent import monkey; monkey.patch_all()   监测代码中所有io行为

    from gevent import monkey; monkey.patch_all()  # 监测代码中所有io行为
    from gevent import spawn
    # gevent本身识别不了time.sleep等不属于该模块内的io操作
    import time
    
    def heng(name):
        print('%s 哼' % name)
        time.sleep(2)
        print('%s 哼' % name)
    
    def ha(name):
        print('%s 哈' % name)
        time.sleep(2)
        print('%s 哈' % name)
    
    start = time.time()
    s1 = spawn(heng, 'egon')
    s2 = spawn(ha, 'tank')
    
    s1.join()
    s2.join()
    print('', time.time()-start)
    # 结果为
    # egon 哼
    # tank 哈
    # egon 哼
    # tank 哈
    # 主 2.1111209392547607
  • 相关阅读:
    1. MySQL的安装与配置
    18. SQL优化
    19. 优化数据库对象
    20. 锁问题
    21. 优化MySQL Server
    整合SSM基本配置
    第七周实验报告(五)&周总结
    Java作业-实验四
    Java实验三
    在IDEA中创建maven工程添加webapp
  • 原文地址:https://www.cnblogs.com/zhangguosheng1121/p/10846823.html
Copyright © 2011-2022 走看看