一、代码结构与功能
这段代码演示了如何用线程池(ThreadPoolExecutor)并发执行多个任务,并通过Future对象管理任务的执行和结果。
二、代码逐行详解
import time
from concurrent.futures import ThreadPoolExecutor, Future
- 导入
time模块用于模拟耗时操作。 - 导入
ThreadPoolExecutor(线程池执行器)和Future(异步任务结果对象)。
def fun(times):
time.sleep(times)
print(f'get html for {times} seconds')
return times
- 定义一个任务函数
fun,参数times表示休眠的秒数。 - 休眠
times秒后,打印一条信息,并返回times。
if __name__ == '__main__':
executor = ThreadPoolExecutor(max_workers=2)
task_time = [4, 2, 3]
for i in task_time:
future = executor.submit(fun, (i))
1. executor = ThreadPoolExecutor(max_workers=2)
- 创建一个线程池对象,最多允许2个线程同时运行。
- 线程池会自动管理线程的创建、复用和销毁。
2. task_time = [4, 2, 3]
- 定义一个任务参数列表,表示要提交3个任务,分别耗时4秒、2秒、3秒。
3. for i in task_time:
- 遍历任务参数列表。
4. future = executor.submit(fun, (i))
- 注意:这里的
(i)其实是一个单元素元组,等价于i。 executor.submit(fun, i):向线程池提交一个任务,执行fun(i),返回一个Future对象。Future对象用于跟踪任务的执行状态和结果。
三、ThreadPoolExecutor和Future的原理
1. ThreadPoolExecutor
- 线程池会维护一个任务队列和一组工作线程。
- 当你调用
submit提交任务时,任务会被放入队列,空闲线程会自动取出任务执行。 max_workers=2表示最多2个线程并发执行任务,其余任务排队等待。
2. Future对象
Future是对异步任务的封装,可以用来:- 检查任务是否完成(
done()) - 获取任务结果(
result(),会阻塞直到任务完成) - 取消任务(
cancel()) - 检查任务是否被取消(
cancelled())
- 检查任务是否完成(
四、任务调度流程
- 提交任务:主线程依次提交3个任务(4秒、2秒、3秒)。
- 线程池调度:
- 最开始有2个线程空闲,分别执行4秒和2秒的任务。
- 2秒任务先完成,线程池空出一个线程,立即开始执行3秒任务。
- 4秒任务最后完成。
- 任务结果:
- 如果你用
future.result()获取结果,会阻塞直到对应任务完成。
- 如果你用
五、易错点说明
executor.submit(fun, (i))中的(i)其实是单元素元组,等价于i。- 推荐直接写
executor.submit(fun, i),更清晰。
- 推荐直接写
- 如果你想收集所有
Future对象,应该用一个列表保存它们,便于后续获取结果或检查状态。
六、完整改进版代码(带结果获取)
import time
from concurrent.futures import ThreadPoolExecutor
def fun(times):
time.sleep(times)
print(f'get html for {times} seconds')
return times
if __name__ == '__main__':
executor = ThreadPoolExecutor(max_workers=2)
task_time = [4, 2, 3]
futures = []
for i in task_time:
future = executor.submit(fun, i) # 推荐直接传i
futures.append(future)
for future in futures:
result = future.result() # 阻塞直到任务完成
print(f'任务完成,返回值:{result}')
七、总结
- 线程池通过
submit方法并发执行任务,返回Future对象用于管理任务状态和结果。 - 线程池能高效复用线程,限制并发数量,避免系统资源耗尽。
Future对象可用于获取任务结果、检查状态、取消任务等。- 推荐直接用
executor.submit(fun, i),避免参数传递歧义。
569

被折叠的 条评论
为什么被折叠?



