当涉及到需要同时执行多个任务的时候,线程就是一个非常方便且高效的解决方案。Python内置了线程操作的模块,名为concurrent
,是一个非常强大的多线程处理工具包。在下面的攻略中,我们将会讲解concurrent
模块中最常用到的功能和具体应用方法。
在开始讲解concurrent
模块之前,我们先来对比一下线程和进程两个概念。
线程是程序中执行的最小单元,是在进程内部的一条执行路径,而进程则是相对独立的运行环境,一个进程中可以包含多个线程。
由于线程是在同一进程内运行的,所以它们之间共享进程的地址空间、文件描述符和其他资源。 这使得线程比进程更加轻量级并限制了各个线程之间的通信成本。
本攻略是基于Python 3.x版本编写。
在concurrent
模块中,常用的方法有以下几个:
ThreadPoolExecutor
: 线程池实现,可以方便地管理线程池中的线程数;ProcessPoolExecutor
: 进程池实现;Future
: 未来对象,用于检查异步调用的结果状态。下面我们将展示如何使用ThreadPoolExecutor
来并发处理任务。
import concurrent.futures
import time
def task(num):
print(f"Task {num} started...")
time.sleep(2)
print(f"Task {num} finished!")
def main():
with concurrent.futures.ThreadPoolExecutor(max_workers=4) as executor:
for i in range(10):
executor.submit(task, i)
if __name__ == "__main__":
main()
输出结果:
Task 0 started...
Task 1 started...
Task 2 started...
Task 3 started...
Task 0 finished!
Task 4 started...
Task 1 finished!
Task 5 started...
Task 2 finished!
Task 6 started...
Task 3 finished!
Task 7 started...
Task 4 finished!
Task 8 started...
Task 5 finished!
Task 9 started...
Task 6 finished!
Task 7 finished!
Task 8 finished!
Task 9 finished!
在这个示例中,我们定义了一个task
函数,它会在执行时打印出任务编号以及执行状态。使用ThreadPoolExecutor
实例,我们可以在一个固定的线程池中并发地执行多个任务。在这个例子中,我们设置了线程池大小为4,然后提交了10个任务。由于线程池中最多只有4个线程,因此实际上会有一些任务需要等待空闲线程。
在下面的这个例子中,我们将演示如何使用Future
对象处理异步任务。
import concurrent.futures
import time
def task(num):
print(f"Starting task {num}...")
time.sleep(2)
print(f"Finished task {num}!")
return f"Result of task {num}"
def main():
with concurrent.futures.ThreadPoolExecutor() as executor:
futures = [executor.submit(task, i) for i in range(10)]
for future in concurrent.futures.as_completed(futures):
print(future.result())
if __name__ == "__main__":
main()
在这个例子中,我们同样定义了一个task
函数,返回任务执行的结果。通过ThreadPoolExecutor
实例,我们提交了10个任务。然后我们在一个循环中,对Future
对象使用as_completed
方法进行检查,以获取已经执行完毕的任务。当一个任务完成时,我们使用result()
方法获取返回结果。
输出结果:
Starting task 0...
Starting task 1...
Starting task 2...
Starting task 3...
Starting task 4...
Starting task 5...
Starting task 6...
Starting task 7...
Starting task 8...
Starting task 9...
Finished task 0!
Result of task 0
Finished task 2!
Result of task 2
Finished task 1!
Result of task 1
Finished task 3!
Result of task 3
Finished task 4!
Result of task 4
Finished task 5!
Result of task 5
Finished task 6!
Result of task 6
Finished task 7!
Result of task 7
Finished task 8!
Result of task 8
Finished task 9!
Result of task 9
我们可以看到,当每个任务完成时,相应的结果都会被打印出来。这样我们就可以在获取所有执行结果后继续处理其他任务。