• 池 concurrent.futrues


    • 什么是池 要在程序开始的时候,还没提交任务先创建几个线程或者进程,放在一个池子里,这就是池

    • 为什么要用池?

      如果先开好进程/线程,那么有任务之后就可以直接使用这个池中的数据了,并且开好的线程或者进程会一直存在在池中,可以被多个任务反复利用,这样极大的减少了开启关闭调度线程/进程的时间开销,池中的线程/进程个数控制了操作系统需要调度的任务个数,是控制池中的单位,有利于提高操作系统的效率,减轻操作系统的负担

    • 发展过程

    1. threading模块 没有提供池

    2. multiprocessing模块 仿照threading写的 Pool

    3. concurrent.futures模块 线程池,进程池都能够用相似的方式开启使用

      线程池
      # 线程池
      import time
      import random
      from threading import current_thread
      from concurrent.futures import ThreadPoolExecutor,ProcessPoolExecutor
      def func(a,b):
          print(current_thread().ident,'start',a,b)
          time.sleep(random.randint(1,4))
          print(current_thread().ident,'end')
      
      if __name__ == '__main__':
          tp = ThreadPoolExecutor(4)
          for i in range(20):
              tp.submit(func,i,b=i+1)  #  提交任务
      
      # 实例化 创建池
      # 向池中提交任务,submit 传参数(按照位置传,按照关键字传)
      View Code
      进程池
      # 进程池
      import os
      import time,random
      from concurrent.futures import ThreadPoolExecutor,ProcessPoolExecutor
      def func(a,b):
          print(os.getpid(),'start',a,b)
          time.sleep(random.randint(1,4))
          print(os.getpid(),'end')
      
      if __name__ == '__main__':
          tp = ProcessPoolExecutor(4)
          for i in range(20):
              tp.submit(func,i,b=i+1)  # submit 提交任务
      View Code

      # map循环提交任务

      import os
      import random
      import time
      from concurrent.futures import ThreadPoolExecutor,ProcessPoolExecutor
      
      
      def func(a):
          print(os.getpid(),'start',a[0],a[1])
          time.sleep(random.randint(1,3))
          print(os.getpid(),'end')
          return a[0]*a[1]
      
      
      if __name__ == '__main__':
          tp = ProcessPoolExecutor(4)
          ret = tp.map(func,((i,i+1)for i in range(10)))  #map 循环提交任务
          for i in ret:
              print(i)
      View Code

      # result() 获取结果

      # 获取任务结果
      import os
      import time,random
      from concurrent.futures import ThreadPoolExecutor,ProcessPoolExecutor
      def func(a,b):
          print(os.getpid(),'start',a,b)
          time.sleep(random.randint(1,4))
          print(os.getpid(),'end')
          return a*b
      
      if __name__ == '__main__':
          tp = ProcessPoolExecutor(4)
          futrue_l = {}
          for i in range(20):         # 异步非阻塞的
              ret = tp.submit(func,i,b=i+1)
              futrue_l[i] = ret
              # print(ret.result())   # Future未来对象
          for key in futrue_l:       # 同步阻塞的
              print(key,futrue_l[key].result())   # result() 获取结果
      View Code

      # add_done_callback 回调函数

      # 回调函数 : 效率最高的
      import time,random
      from threading import current_thread
      from concurrent.futures import ThreadPoolExecutor
      
      def func(a,b):
          print(current_thread().ident,'start',a,b)
          time.sleep(random.randint(1,4))
          print(current_thread().ident,'end',a)
          return (a,a*b)
      
      def print_func(ret):       # 异步阻塞
          print(ret.result())
      
      if __name__ == '__main__':
          tp = ThreadPoolExecutor(4)
          for i in range(20):         # 异步非阻塞的
              ret = tp.submit(func,i,b=i+1)
              ret.add_done_callback(print_func)  # ret这个任务会在执行完毕的瞬间立即触发print_func函数,并且把任务的返回值对象传递到print_func做参数
             # 异步阻塞 回调函数 给ret对象绑定一个回调函数,等待ret对应的任务有了结果之后立即调用print_func这个函数
             # 就可以对结果立即进行处理,而不用按照顺序接收结果处理结果
              
             # add_done_callback 回调函数
      View Code
    4. #进程池(高计算的场景,没有io(没有文件操作没有数据库操作没有网络操作没有input)) : >cpu_count*1 <cpu_count*2
      # 线程池(一般根据io的比例定制) : cpu_count*5
      # 5*20 = 100并发

  • 相关阅读:
    继承与多态
    本周总结
    总结
    周总结
    周总结
    第三周总结
    .......
    .....
    ....
    ....
  • 原文地址:https://www.cnblogs.com/biu-py/p/11107692.html
Copyright © 2020-2023  润新知