文章目录
前言
线程池是计算机编程中用于管理一组预先创建的线程的机制,这些线程可以被复用以执行多个任务。线程池的主要目的是提高程序的效率和响应性,通过减少线程创建和销毁的开销,以及合理分配线程资源来处理任务。
一、线程池的使用
在Python中,concurrent.futures模块提供了线程池的实现。ThreadPoolExecutor是该模块中用于创建线程池的类。以下是一个使用ThreadPoolExecutor创建线程池并执行任务的例子:
from concurrent.futures import ThreadPoolExecutor
# 创建一个包含5个线程的线程池
pool = ThreadPoolExecutor(5)
# 定义一个函数,该函数将被线程池中的线程执行
def task_function(x):
return x * x
# 使用线程池执行任务
results = [pool.submit(task_function, i) for i in range(10)]
# 获取所有任务的结果
for future in results:
print(future.result())
在这个例子中:
- ThreadPoolExecutor(5)创建了一个包含5个线程的线程池。
- task_function是一个简单的函数,它将输入值平方。
- pool.submit(task_function,i)将任务提交给线程池,submit方法返回一个Future对象,可以用来获取任务的结果。
- 通过future.result()获取每个任务的结果。
再来个例子思考体会一下:
import math
import concurrent.futures
def calculate_factorial(number):
"""计算一个数的阶乘"""
return math.factorial(number)
def main():
numbers = [1, 2, 3, 4, 5] # 任务列表,计算这些数的阶乘
# 创建一个包含3个线程的线程池
with concurrent.futures.ThreadPoolExecutor(max_workers=3) as executor:
# 使用submit函数来提交任务
futures = {executor.submit(calculate_factorial, number): number for number in numbers}
# 获取并打印结果
for future in concurrent.futures.as_completed(futures):
number = futures[future]
try:
result = future.result()
except Exception as exc:
print(f"{number} generated an exception: {exc}")
else:
print(f"The factorial of {number} is {result}")
if __name__ == "__main__":
main()
The factorial of 2 is 2
The factorial of 1 is 1
The factorial of 3 is 6
The factorial of 4 is 24
The factorial of 5 is 120
代码解析:
- 提交任务:使用executor.submit()方法将任务提交给线程池。submit()方法返回一个Future对象,该对象代表了正在执行的任务。我们使用字典futures来存储Future对象和对应的数字,以便在任务完成后可以找到原始的数字。
- 获取结果:使用concurrent.futures.as_completed()函数来迭代已完成的Future对象。当一个任务完成时,我们调用future.result()来获取任务的结果。如果任务执行过程中抛出了异常,result()方法会重新抛出这个异常,我们可以在try…except语句中捕获它。
- 处理异常:在try…except语句中,我们检查future.result()是否抛出异常。如果抛出异常,我们打印出异常信息;如果没有异常,我们打印出结果。
使用map函数来提交任务并保持执行顺序
import math
import concurrent.futures
def calculate_factorial(number):
"""计算一个数的阶乘"""
return math.factorial(number)
def main():
numbers = [1, 2, 3, 4, 5] # 任务列表,计算这些数的阶乘
# 创建一个包含3个线程的线程池
with concurrent.futures.ThreadPoolExecutor(max_workers=3) as executor:
# 使用map函数来提交任务并保持执行顺序
# 使用executor.map()方法将任务提交给线程池。与executor.submit()不同,map()方法会等待所有任务完成,并返回一个结果列表,保持了输入列表的顺序
results = executor.map(calculate_factorial, numbers)
# 打印结果
for number, result in zip(numbers, results):
print(f"The factorial of {number} is {result}")
if __name__ == "__main__":
main()
The factorial of 1 is 1
The factorial of 2 is 2
The factorial of 3 is 6
The factorial of 4 is 24
The factorial of 5 is 120
二、线程池的工作流程
- 当线程数小于核心线程数时,每提交一个任务就创建一个线程来执行,即使当前有线程处于空闲状态,直到当前线程数达到核心线程数
- 当前线程数达到核心线程数时,如果这个时候还提交任务,这些任务会被放到工作队列里,等到线程处理完了手头的任务后,会从队列中取任务处理。
- 当前线程数达到核心线程数并且工作队列也满了,如果这个时候还提交任务,则会继续创建线程来处理,直到线程数达到最大线程数。
- 当前线程数达到最大线程数并且队列也满了,如果这个时候还提交任务,则会触发饱和策略,如抛出异常或拒绝执行任务。
三、线程池的优势
- 资源消耗降低:通过重复利用已创建的线程,线程池可以降低线程创建和销毁造成的资源消耗。
- 提高响应速度:当任务到达时,线程池中的线程可以立即执行任务,而无需等待新线程的创建。
- 提高线程的可管理性:线程是稀缺资源,无限制的创建线程不仅会消耗系统资源,还会降低系统的稳定性。使用线程池可以进行统一分配、调优和监控。
四、总结
通过合理配置线程池的参数,如核心线程数、最大线程数、工作队列大小和饱和策略,可以有效地管理线程资源,提高程序的性能和稳定性。
标签:python,futures,number,学习,factorial,任务,线程,result From: https://blog.csdn.net/weixin_43574373/article/details/142058049