python3使用ThreadPoolExecutor小记
ThreadPoolExecutor是python里的一个个人觉得特别好用的线程类。
刚开始接触的时候,只是很简单的用map或者submit,现在来介绍一下它的用法。
1. 导入
from concurrent.futures import ThreadPoolExecutor, as_completed
可以看到包是 concurrent.futures
导入了 ThreadPoolExecutor 和 as_completed,as_completed的作用是判断线程池内的所有线程是否执行完毕,用以作结束判断。
2. map的使用
def thread_func(info):
print(threading.current_thread().name)
print(info)
if __name__ == "__main__":
with ThreadPoolExecutor(max_workers=5) as thread_pool:
thread_pool.map(thread_func, [1, 2, 54, 100])
map在使用的时候,map(param_1, param_2)
param_1 为要执行的函数,param_2 为要传递给函数的参数(应是一个列表),他应该是一个可迭代对象,比如list()。每一个list里的元素都是对应的参数,比如我这里的 1, 2, 54, 100会分别当成参数传递给每一个线程的thread_func。传递的参数(可迭代对象)有多少个元素,就会执行多少个线程。
3. submit的使用
def thread_func(info):
print(threading.current_thread().name)
print(info)
if __name__ == "__main__":
with ThreadPoolExecutor(max_workers=5) as thread_pool:
for i in range(10):
thread_pool.submit(thread_func, i)
submit在使用的时候, submit(param_1, *args, **kwargs)
param_1 为要执行的函数与map一样, 后面紧跟的则是参数列表了,都为要传递给函数的参数,submit只会开启一个线程,所有可以配合 for循环进行线程的开启。
4. 注意:
此处就是本文出生的主要原因, 要用with启动ThreadPoolExecutor,否则你就需要手动调用 ThreadPoolExecutor的一个方法:ThreadPoolExecutor.shutdown(),如果没有调用也没有用with,则很可能会造成资源泄露等严重问题。
5. 安利一波自己造的线程启动小函数:
def start_thread(self, data, fun, max_worker=15, is_test=False, **kwargs):
"""
This function can start a thread pool
:param is_test:
:param max_worker:
:param data:
:param fun:
:param kwargs:
:return:
"""
result = list()
with ThreadPoolExecutor(max_workers=max_worker) as thread_pool:
task_list = list()
for item in data:
task = thread_pool.submit(fun, item, **kwargs)
task_list.append(task)
if is_test:
break
for i in as_completed(task_list):
result.append(i.result())
return result
调用的时候只需要执行
start_thread(data, fun) 即可,data与map的第一个类似,应该是一个可迭代对象,他是一个必须参数,函数靠他来判断启动多少个线程, start_thread会返回一个 执行函数的结果列表。