Python线程池thread pool创建使用及实例代码分享
Python线程池(thread pool)是一种提供线程复用的机制,通过线程池的管理,可以减少线程创建与销毁的代价,并提升异步并发执行的性能,同时避免资源的浪费,使用起来也相对方便和稳定。本篇攻略将详细介绍如何在Python中使用线程池,通过实例代码的分享帮助读者更好的掌握线程池的使用和工作原理。
创建线程池
Python内置了线程池的支持,使用concurrent.futures
模块中的ThreadPoolExecutor
类可以方便地创建线程池。
首先,需要导入concurrent.futures
模块,以及time
模块用于辅助时间计算。
import concurrent.futures
import time
然后,可以通过如下方式创建一个具有4个线程的线程池。
with concurrent.futures.ThreadPoolExecutor(max_workers=4) as executor:
# TODO: 任务列表
可以看到,在创建线程池时,可以通过max_workers
参数指定线程池中线程的数量,具体数量应该根据具体的场景来确定。同时,在使用完线程池后,需要使用with
语句来自动管理线程池的资源。
提交任务
线程池中的工作线程需要执行的任务通过提交操作放入线程池中,线程池会自动选择适当的线程来执行任务。一般情况下,任务都是使用函数的形式传递给线程池。
举个例子,假设有一个需要执行的计算任务,可以通过如下方式定义计算函数。
def compute(num):
result = num * num
time.sleep(1) # 模拟耗时操作
return result
该函数接收一个参数num
,返回num
的平方,并使用time.sleep
函数模拟耗时操作。
接下来,可以通过使用submit
方法将任务提交到线程池中。
with concurrent.futures.ThreadPoolExecutor(max_workers=4) as executor:
future_list = []
for i in range(10):
future = executor.submit(compute, i)
future_list.append(future)
可以看到,在遍历任务列表时,可以使用submit
方法将任务提交到线程池中,并使用future_list
保存任务的结果。submit
方法的第一个参数是需要执行的函数,后续的参数是函数的输入参数。
获取结果
线程池中的任务是异步执行的,因此主线程需要使用future
对象来获取线程执行的结果。future
对象对应一个线程任务,其中包含了线程执行结果和执行状态等参数。
可以使用done
方法判断任务是否已经完成,使用result
方法获取任务的返回值,如下所示。
with concurrent.futures.ThreadPoolExecutor(max_workers=4) as executor:
future_list = []
for i in range(10):
future = executor.submit(compute, i)
future_list.append(future)
for future in concurrent.futures.as_completed(future_list):
if future.done():
print("result: {}".format(future.result()))
可以看到,在使用as_completed
方法迭代线程任务时,可以使用future.done()
方法判断线程是否执行完,使用future.result()
方法获取线程执行结果。
示例说明1:异步下载图片
假设要异步下载多张图片并保存到本地,可以通过使用线程池实现,具体步骤如下。
首先,需要导入requests
模块和os
模块,后者用于保存图片。
import requests
import os
然后,可以定义下载函数,将图片和本地文件名作为输入参数。
def download_img(url, filename):
response = requests.get(url, stream=True)
with open(filename, 'wb') as f:
for chunk in response.iter_content(1024):
f.write(chunk)
注意,download_img
函数将使用requests.get
方法下载图片内容,并使用stream=True
参数设置为分块读取,以便在下载大文件时不会占用太多内存。下载完成后,将图片内容保存到指定的文件中。
接下来,可以通过使用线程池,并构造许多下载任务来完成异步下载图片的工作。
with concurrent.futures.ThreadPoolExecutor(max_workers=4) as executor:
urls = ["https://picsum.photos/200/300?random={}".format(i) for i in range(10)]
filenames = [os.path.join(os.getcwd(), "img{}.jpg".format(i)) for i in range(10)]
future_list = []
for i in range(10):
future = executor.submit(download_img, urls[i], filenames[i])
future_list.append(future)
for future in concurrent.futures.as_completed(future_list):
if future.done():
print("download {} complete".format(future.args[1]))
在上面的代码中,首先构造了10个图片的URL和下对应的文件名,并使用线程池构造了10个下载任务,并将任务的future对象保存在列表中。随后,可以使用as_completed
方法依次判断并输出每个任务的状态。
示例说明2:并发执行多个命令
假设要在本地同时执行多个操作系统命令,并等待所有命令执行完成后再输出相应结果,可以通过使用线程池实现。
首先,需要将命令列表构造出来。
commands = ['echo Hello', 'echo World', 'ls -l']
然后,定义命令执行函数。
def run_command(command):
print("Running command: {}".format(command))
result = os.popen(command).read()
time.sleep(1) # 模拟耗时操作
return result
在该函数中,首先输出将要执行的命令,然后使用os.popen
执行相应命令,并将执行结果保存到返回值中。
然后,可以通过使用线程池,并构造许多命令执行任务来完成异步执行命令的工作。
with concurrent.futures.ThreadPoolExecutor(max_workers=4) as executor:
future_list = []
for command in commands:
future = executor.submit(run_command, command)
future_list.append(future)
for future in concurrent.futures.as_completed(future_list):
if future.done():
print("result: {}".format(future.result()))
在上述代码中,首先构造了命令列表,并使用线程池构造了多个命令任务,并将任务的future对象保存在列表中。随后,可以使用as_completed
方法依次判断并输出每个任务的执行结果。
总结
Python线程池提供了高效的管理方式和执行异步任务的能力,同时使用也非常简单明了,可以极大提升代码的执行效率和并行性。通过上述示例,相信读者已经对Python线程池有了一定的了解,可以在实际项目中灵活应用。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Python线程池thread pool创建使用及实例代码分享 - Python技术站