concurrent.futures模块(进程池&线程池)

1、线程池的概念

  由于python中的GIL导致每个进程一次只能运行一个线程,在I/O密集型的操作中可以开启多线程,但是在使用多线程处理任务时候,不是线程越多越好,因为在线程切换的时候,需要切换上下文环境,这样会导致CPU的大量开销,同时产生大量的切换时间浪费。为了解决这个问题,线程池概念被提出。预先创建好一个较为优化的数量的线程,让过来的任务立刻能够使用,就形成了线程池。python中的concurrent.futures模块为我们做了很好地封装,该模块为我们封装了线程池和进程池。

2、最佳线程数的获取:

  1、通过用户慢慢递增来进行性能压测,观察QPS(即每秒的响应请求数,也即是最大吞吐能力。),响应时间

  2、根据公式计算:服务器端最佳线程数量=((线程等待时间+线程cpu时间)/线程cpu时间) * cpu数量

  3、单用户压测,查看CPU的消耗,然后直接乘以百分比,再进行压测,一般这个值的附近应该就是最佳线程数量。

3、concurrent.futures模块中的线程池

from concurrent.futures import ThreadPoolExecutor
import time,os
def fn(name):
    print('%s %s is running' %(name,os.getpid()))
    time.sleep(3)
if __name__=="__main__":
    p=ThreadPoolExecutor(5) #设置线程池线程数
    for i in range(10):
        obj=p.submit(fn,'线程pid:') #submit(fn, *args, **kwargs)
    res=obj.result() #注意:submit提交后返回的结果是一个future对象,需要使用obj.result才能获取想要的字符串等结果
    p.shutdown(wait=True) # 关闭线程池的入口,等待池内任务运行结束

4、concurrent.futures模块中的进程池

from concurrent.futures import ProcessPoolExecutor
import time,os
def fn(name):
    print('%s %s is running' %(name,os.getpid()))
    time.sleep(3)
if __name__=="__main__":
    p=ProcessPoolExecutor(5) #设置进程池线程数
    for i in range(10):
        obj=p.submit(fn,'进程pid:') #submit(fn, *args, **kwargs)
    res=obj.result() #注意:submit提交后返回的结果是一个future对象,需要使用obj.result才能获取想要的字符串等结果
    p.shutdown(wait=True) # 关闭进程池的入口,等待池内任务运行结束

猜你喜欢

转载自www.cnblogs.com/dushangguzhousuoli/p/10859166.html