likes
comments
collection
share

ThreadPoolExecutor线程池和ProcessPoolExecutor进程池

作者站长头像
站长
· 阅读数 56

前言

标准库concurrent.futures模块,它提供了ProcessPoolExecutor和ThreadPoolExecutor两个类,
实现了对threading和multiprocessing的进一步抽象.

1/ThreadPoolExecutor线程池

ThreadPoolExecutor()构造实例的时候,传入[max_workers]()参数来设置线程中最多能同时运行的线程数目
   使用submit()函数来提交线程需要执行任务(函数名和参数)到线程池中,并返回该任务的句柄(类似于文件、画图),注意[submit()]()不是阻塞的,而是立即返回。
  通过submit()函数返回的任务句柄,能够使用done()()方法判断该任务是否结束
  使用result()方法可以获取任务的返回值,查看内部代码,发现这个方法是阻塞的
  
# -*-coding:utf-8 -*- 
from concurrent.futures import ThreadPoolExecutor 
import time # 参数times用来模拟网络请求时间 


def f(times): 
    print("get page {}s finished".format(times)) 
    return times 

# 构建多线程池子
executor = ThreadPoolExecutor(max_workers=2) 

# 通过submit函数提交执行的函数到线程池中,submit函数立即返回,不阻塞 
task1 = executor.submit( f,(3) ) 
task2 = executor.submit( f,(2) ) 

#done方法用于判断某个任务是否完成 
print(task1.done()) 

#cancel方法用于取消某个任务,该任务没有放到线程池中才能被取消
print(task2.cancel()) 

print(task1.done()) 

#result方法可以获取task的执行结果 
print(task1.result()) 

#结果: 
# get page 3s finished 
# get page 2s finished 
# True 
# False 
# True 
# 3
  

2/ProcessPoolExecutor进程池

  有2种任务提交方式
  
  <1>同步提交方式
     提交任务,原地等待任务执行结束,拿到任务返回结果,再执行接下来的任务
     优点:可以解耦合
     缺点:速度慢,因为需要等结果,然后再执行下一个


  import datetime
  from concurrent.futures import ProcessPoolExecutor
  from threading import current_thread
  import time, random, os
  import requests
  
  def f(name):
      print('%s %s is running'%(name,os.getpid()))
      #print(datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"))
      
  if __name__ == '__main__':
      process_pool = ProcessPoolExecutor(4) # 设置进程池内进程数
      for i in range(10):
          # 同步调用方式,调用和等值
          # 传参方式(任务名,参数),参数使用位置或者关键字参数
          obj = process_pool.submit(f,"进程pid:")
          
          # .result()函数,得到进程的返回结果,及return的结果
          # 如果f()函数中没有return,则obj.result()是None
          res = obj.result()
          
      # 关闭进程池的入口,等待池内任务运行结束,再执行主程序
      process_pool.shutdown(wait=True) 
      
      print("主线程")
   <2>异步提交方式
      只调用,不等值
      优点:速度快
      缺点:存在耦合

    import datetime
    from concurrent.futures import ProcessPoolExecutor
    from threading import current_thread
    import time, random, os
    import requests
    
    def f(name): 
        print("%s %s is running" %(name,os.getpid())) 
        time.sleep(random.randint(1,3)) 
    
    if __name__ == '__main__': 
        #设置进程池内进程 
        process_pool = ProcessPoolExecutor(4)
        
        for i in range(10): 
            # 异步提交方式,只调用,不等值 
            process_pool.submit(f,'进程pid:') 
            # 传参方式(任务名,参数),参数使用位置参数或者关键字参数
        
        # 关闭进程池的入口,等待池内任务运行结束,再执行主程序
        process_pool.shutdown( wait=True ) 
        
        print('主线程')

总结

1、线程不是越多越好,会涉及cpu上下文的切换(会把上一次的记录保存)。

2、进程比线程消耗资源,进程相当于一个工厂,工厂里有很多人,里面的人共同享受着福利资源,,一个进程里默认只有一个主线程,比如:开启程序是进程,里面执行的是线程,线程只是一个进程创建多个人同时去工作。

3、线程里有GIL全局解锁器:不允许cpu调度

4、计算密度型(cpu密集型)适用于多进程
4.1 I/O密集型适合多线程,谁有空谁执行

5、线程:线程是计算机中工作的最小单元

6、进程:默认有主线程 (帮工作)可以多线程共存

7、协程:一个线程,一个进程做多个任务,使用进程中一个线程去做多个任务,微线程

8、GIL全局解释器锁:保证同一时刻只有一个线程被cpu调度
转载自:https://juejin.cn/post/7018014070318039053
评论
请登录