在现代编程中,提高程序的执行效率是开发者关注的重点。Python作为一门高级编程语言,提供了多种实现并发(Concurrency)和并行(Parallelism)的方法。本文将详细介绍并发与并行的概念、它们在Python中的实现方式,以及相关的示例代码。
文章目录
并发与并行的概念
并发是指在同一时间段内,多个任务交替执行,但在某一时刻只有一个任务在运行。它适用于I/O密集型任务,例如文件读写、网络请求等操作,因为这些操作通常会涉及等待外部资源响应。
并行是指在同一时间内,多个任务同时运行。它适用于CPU密集型任务,例如复杂的计算和数据处理,因为这些任务需要大量的CPU资源。
简单来说,并发是逻辑上的同时发生,而并行是物理上的同时发生。
Python中的并发实现
1. 使用threading
模块实现多线程
Python的threading
模块提供了创建和管理线程的功能。线程是操作系统能够进行运算调度的最小单位,它被包含在进程之中,是进程中的实际运作单位。一个进程可以创建多个线程。
以下是一个使用threading
模块的示例:
import threading
import time
def worker(num):
"""线程执行的函数"""
print(f"线程 {num} 开始")
time.sleep(2)
print(f"线程 {num} 结束")
threads = []
for i in range(5):
t = threading.Thread(target=worker, args=(i,))
threads.append(t)
t.start()
for t in threads:
t.join()
print("所有线程执行完毕")
在上述代码中,我们创建了5个线程,每个线程都会调用worker
函数,并传入不同的参数。使用threading.Thread
创建线程对象,并使用start()
方法启动线程。最后,使用join()
方法等待所有线程执行完毕。
需要注意的是,由于Python的全局解释器锁(GIL)的存在,Python的多线程在CPU密集型任务上并不能实现真正的并行。因此,多线程更适用于I/O密集型任务。
2. 使用concurrent.futures
模块的ThreadPoolExecutor
concurrent.futures
模块提供了更高级的接口来管理线程和进程。ThreadPoolExecutor
是一个基于线程池的执行器,可以用来并发地执行任务。
以下是一个使用ThreadPoolExecutor
的示例:
from concurrent.futures import ThreadPoolExecutor
import time
def worker(num):
"""线程池中的线程执行的函数"""
print(f"线程 {num} 开始")
time.sleep(2)
print(f"线程 {num} 结束")
with ThreadPoolExecutor(max_workers=5) as executor:
for i in range(5):
executor.submit(worker, i)
print("所有线程池中的线程执行完毕")
在上述代码中,使用ThreadPoolExecutor
创建了一个包含最多5个线程的线程池。然后,使用submit()
方法提交了5个任务到线程池中。with
语句块结束后,线程池会自动等待所有任务完成并关闭。
Python中的并行实现
1. 使用multiprocessing
模块实现多进程
Python的multiprocessing
模块允许创建子进程,并提供了与threading
模块类似的API。由于每个进程都有自己的内存空间,因此可以绕过GIL,实现真正的并行。
以下是一个使用multiprocessing
模块的示例:
from multiprocessing import Process
import time
def worker(num):
"""进程执行的函数"""
print(f"进程 {num} 开始")
time.sleep(2)
print(f"进程 {num} 结束")
processes = []
for i in range(5):
p = Process(target=worker, args=(i,))
processes.append(p)
p.start()
for p in processes:
p.join()
print("所有进程执行完毕")
在上述代码中,我们创建了5个进程,每个进程都会调用worker
函数,并传入不同的参数。使用Process
创建进程对象,并使用start()
方法启动进程。最后,使用join()
方法等待所有进程执行完毕。
2. 使用concurrent.futures
模块的ProcessPoolExecutor
concurrent.futures
模块还提供了ProcessPoolExecutor
,它是一个基于进程池的执行器,可以用来并行地执行任务。
以下是一个使用ProcessPoolExecutor
的示例:
from concurrent.futures import ProcessPoolExecutor
import time
def worker(num):
"""进程池中的进程执行的函数"""
print(f"进程 {num} 开始")
time.sleep(2)
print(f"进程 {num} 结束")
with ProcessPoolExecutor(max_workers=5) as executor:
for i in range(5):
executor.submit(worker, i)
print("所有进程池中的进程执行完毕")
在上述代码中,使用ProcessPoolExecutor
创建了一个包含最多5个进程的进程池。然后,使用submit()
方法提交了5个任务到进程池中。with
语句块结束后,进程池会自动等待所有任务完成并关闭。
另一个示例(来源于Concurrency vs Parallelism)
选择并发或并行的原则
-
I/O密集型任务:适用于并发编程,例如文件读写、网络请求等操作。可以使用
threading
模块或concurrent.futures.ThreadPoolExecutor
来实现。 -
CPU密集型任务:适用于并行编程,例如复杂的计算和数据处理等操作。可以使用
multiprocessing
模块或concurrent.futures.ProcessPoolExecutor
来实现。
需要根据具体的任务类型选择合适的并发或并行编程方式,以充分利用系统资源,提高程序的执行效率。