python3多线程有threading,很好的支持了多线程,那么问题来了,为什么还需要线程池呢,其实很好回答,如果你要爬取网站有八百页,每页设置一个线程,难道能开启八百个么,光切换的时间也很高了吧。这时候就需要用到线程池,可以设置一个20的线程池,同时只有20个线程在运行,剩下的排队。
线程池模块
在threading中是没有线程池相关功能的,想要运行线程池需要自己重写,很明显像我这么懒不可能重写,而且自己编写线程池很难写的比较完美,还需要考虑复杂情况下的线程同步,很容易发生死锁。所以就用到了这个模块,
from concurrent.futures import ThreadPoolExecutor
从Python3.2开始,标准库为我们提供了concurrent.futures模块,它提供了ThreadPoolExecutor和ProcessPoolExecutor两个类,实现了对threading和multiprocessing的进一步抽象(线程池和进程池的唯一区别就是线程与进程,使用方法,内置函数等都完全一样),可以帮我们自动调度线程,省下大量时间
def thread_text(i,y): time.sleep(i+y) return i+y if __name__ == '__main__': executor = ThreadPoolExecutor(max_workers=5) # max_workers :设置进程池中线程数量 executor1 = executor.submit(thread_text, 1,1) # 和线程不同,进程池传参,不用以元组形式。进程池如果需要传递多个参数,只需要按照参数位置跟在后面即可 executor2 = executor.submit(thread_text, 2,1) executor.shutdown() # 关闭线程池
首先需要实例化,然后在实例化的同时设置最大线程数,然后使用submit提交线程就ok啦,而且与threading.Thread 的线程不同的是,线程池不阻塞,立即执行,也就是说,不需要start来启动它,
知识点一:线程池不阻塞,不需要start
而且想必有些同学已经看出我这个例子的常规例子的不同了,那就是我传了两个参数,这里也是为了区别threading.Thread的参数,众所周知,threading模块对方法传入参数是以元组的形式,比如我上面写的方法,如果用threading调用的话应该这么写threading.Thread(target=thread_text,args=(1,1)),而线程池则不是,如果翻过源码会发现ThreadPoolExecutor没有固定参数,只有*args和**kwargs,所以,线程池如果要传入多个参数,只需要按照参数位置跟在后面即可。
知识点二:线程池传参不要元组,接着往后写,有多少写多少
介绍一下其他几个常用功能函数:
wait 函数 :等待线程任务完成
wait(executor1, executor2)
result 函数 : 获取每个任务的结果
from concurrent.futures import ThreadPoolExecutor,as_completed import time def thread_text(i,y): time.sleep(i+y) return i+y if __name__ == '__main__': executor = ThreadPoolExecutor(max_workers=5) executor1 = executor.submit(thread_text, 1, 1) executor2 = executor.submit(thread_text, 2, 1) executor.shutdown() print(executor1.result()) print(executor2.result())
as_completed:上面虽然提供了判断任务是否结束的方法,但是不能在主线程中一直判断啊。有时候我们是得知某个任务结束了,就去获取结果,而不是一直判断每个任务有没有结束。这是就可以使用as_completed方法一次取出所有任务的结果。
from concurrent.futures import ThreadPoolExecutor,as_completed def thread_text(i,y): time.sleep(i+y) return i+y if __name__ == '__main__': executor = ThreadPoolExecutor(max_workers=5) executor1 = executor.submit(thread_text, 1,1) executor2 = executor.submit(thread_text, 2,1) for i in as_completed([executor1,executor2]): print(i.result()) executor.shutdown()
一个demo示例:
pool = ThreadPoolExecutor(max_workers=4) # 创建线程池 resultlist = [pool.submit(address.distance_caculate, cou, i) for i in list1] # list1任务列表,通过for 循环向线程池中提交任务 wait(resultlist) # 等待任务完成 new_list = [i.result() for i in resultlist] # 使用 .result() 方法获取每个任务的结果
原文链接:https://blog.csdn.net/weixin_45621200/article/details/123849354