python 线程池的使用

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了python 线程池的使用相关的知识,希望对你有一定的参考价值。

参考技术A 最近在做一个爬虫相关的项目,单线程的整站爬虫,耗时真的不是一般的巨大,运行一次也是心累,,,所以,要想实现整站爬虫,多线程是不可避免的,那么python多线程又应该怎样实现呢?这里主要要几个问题(关于python多线程的GIL问题就不再说了,网上太多了)。

一、 既然多线程可以缩短程序运行时间,那么,是不是线程数量越多越好呢?

显然,并不是,每一个线程的从生成到消亡也是需要时间和资源的,太多的线程会占用过多的系统资源(内存开销,cpu开销),而且生成太多的线程时间也是可观的,很可能会得不偿失,这里给出一个最佳线程数量的计算方式:

最佳线程数的获取:

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

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

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

二、为什么要使用线程池?

对于任务数量不断增加的程序,每有一个任务就生成一个线程,最终会导致线程数量的失控,例如,整站爬虫,假设初始只有一个链接a,那么,这个时候只启动一个线程,运行之后,得到这个链接对应页面上的b,c,d,,,等等新的链接,作为新任务,这个时候,就要为这些新的链接生成新的线程,线程数量暴涨。在之后的运行中,线程数量还会不停的增加,完全无法控制。所以,对于任务数量不端增加的程序,固定线程数量的线程池是必要的。

三、如何使用线程池
过去使用threadpool模块,现在一般使用concurrent.futures模块,这个模块是python3中自带的模块,但是,python2.7以上版本也可以安装使用,具体使用方式如下:

注意到:
concurrent.futures.ThreadPoolExecutor,在提交任务的时候,有两种方式,一种是submit()函数,另一种是map()函数,两者的主要区别在于:

Python爬虫基础讲解(十八):线程池的使用

Python爬虫、数据分析、网站开发等案例教程视频免费在线观看

https://space.bilibili.com/523606542 

 

Python学习交流群:1039649593

 

线程池的使用

ThreadPoolExecutor

有一种比你上面看到的更简单的方法来启动一组线程。它被称为a ThreadPoolExecutor,它是标准库的一部分concurrent.futures(从Python 3.2开始)。

创建它的最简单方法是作为上下文管理器,使用该with语句来管理池的创建和销毁。

import concurrent.futures
import time

def thread_function(name) :
    print("子线程%s:启动”% name)
    time.s1eep(2)
    print("子线程%s:完成”% name)
if __name__ == "_main__":
    with concurrent.futures.ThreadPoo1Executor(max_workers=3) as executor":
    for i in range(10):
        executor.submit(thread_function,i)

 

代码创建一个ThreadPoo1Executor 上下文管理器,告诉它在池中需要多少个工作线程。然后,它.map()会逐步执行可迭代的事物,在您的情况下range(3),将每个事物传递给池中的线程。

with块的结尾导致在池中的每个线程上ThreadPoo7Executor执行a .join())。这是强烈建议您使用ThreadPoo1Executor的上下文管理器时,你可以让你永远不会忘记.join()的线程。

示例代码将生成如下所示的输出:

子线程0:启动
子线程1:启动
子线程2:启动
子线程2:完成
子线程0:完成
子线程1:完成

 

多线程的优缺点

优点:

  • 多线程技术使程序的响应速度更快,让程序高效率的执行
  • 提升了计算能力

缺点:

  • 多线程是没有绝对执行顺序的(理解)
  • 等候使用共享资源时造成程序的运行速度变慢。这些共享资源主要是独占性的资源,如如全局变量。
  • 对线程进行管理要求额外的CPU开销。线程的使用会给系统带来上下文切换的额外负担。当这种负担超过一定程度时,多线程的特点主要表现在其缺点上,比如用独立的线程来更新数组内每个元素。
  • 线程的死锁。即较长时间的等待或资源竞争以及死锁等多线程症状。

以上是关于python 线程池的使用的主要内容,如果未能解决你的问题,请参考以下文章

python 线程池的使用

python中设置线程池最大数量不管用

python线程池和进程池的多参数调用

Java线程池的使用

线程池的使用

线程池的学习和使用