Python进程池和线程池
Python 进程池
进程池是一种并发编程概念,用于管理多个进程的创建、执行和终止,进程池中进程可并行执行,以提高效率。是 多进程操作。
优点:
- 提高性能:将任务分配给多个进程,进程池可充分利用多核处理器优势,提高执行速度。
- 简化编程:通过API将任务提交给进程池,进程池会自动处理任务的调度和执行。
- 资源管理:进程池可自动管理进程创建和销毁及内存等分配。能防止资源泄漏、过度分配。
缺点:
- 开销:创建维护进程池产生一定开销,尤进程数较多时。对轻量级任务可能导致性能下降。
- 并发问题:多进程环境需注意数据同步和共享的问题,以避免死锁等并发问题。
适用场景:
- 计算密集型任务:需大量计算的任务,进程池可充分利用多核处理器优势,提高执行速度。
- 并行任务执行:若有许多独立任务需执行,且任务间无依赖关系,则进程池是很好的选择。
- 有限资源的分配:当需限制并发任务数时,进程池可帮助管理资源分配,避免过度分配。
Python中的进程池可以用来管理一组工作进程,可以并发执行多个任务,特别对多个计算密集型任务时,可充分利用多核CPU(通常可将进程池的大小设置为CPU核心数量的2倍)。
步骤一般是:①导入multiprocessing的Pool类;②创建进程池对象,指定N个工作进程;
pool = Pool(processes=4)
③执行任务(常见apply_async(A, B)方法,A为执行函数,B为函数参数列表;map(A, B)方法将函数A执行到列表B的每一个元素);④用close()或join等待全部任务完成,还有一种常用操作是sleep等待时间:
time.sleep(1)
另外使用with的方式调进程池,能保证使用后自动关闭,类似调用文件一般。
给两个最简洁的实例即:
from multiprocessing import Poolwith Pool(processes=POOL_SIZE) as pool:pool.map(A, B)
time.sleep(1)
from multiprocessing import Pooldef square(x):return x * xwith Pool(processes=4) as pool: # 进程池工作进程数为4numbers = [1, 2, 3, 4, 5]results = pool.map(square, numbers) # 将square施加到numbers每个元素上print("Results:", results) # Results: [1, 4, 9, 16, 25]
Python 线程池
线程池是一种并发编程概念,用于管理多个线程的创建、执行和终止,线程池中线程可并行执行,以提高效率。是多线程操作。
优点:
- 提高性能:任务分配给多个线程,提高 I/O 密集型任务的执行速度。
- 简化编程:通过API将任务提交给线程池,线程池会自动处理任务的调度和执行。
- 资源管理:线程池可自动管理线程的创建和销毁。这有助于防止资源泄漏和过度分配。
缺点:
- 开销:创建维护线程池产生一定开销,尤线程数较多时。对轻量级任务可能导致性能下降。
- 并发问题:多线程环境需注意数据共享的问题,以避免死锁等并发问题。
- GIL(全局解释器锁)限制:在 CPython(Python 的常用实现)中,全局解释器锁(GIL)阻止了多线程的并行执行。GIL 确保在任何时刻只有一个线程在执行,即使在多核处理器上。因此,在 CPython 中,多线程无法实现真正的并行操作。但请注意,其他 Python 实现(如 Jython 或 IronPython)没有 GIL 限制,因此它们可以实现多线程的并行执行。
适用场景:
- I/O 密集型任务:需大量 I/O 操作(如网络请求、文件读写等)的任务。
- 并行任务执行:许多独立任务需执行,而任务间没依赖关系。
- 有限资源的分配:当限制并发任务数时,线程池可帮助您管理资源分配,避免过度分配。
ThreadPoolExecutor
from concurrent.futures import ThreadPoolExecutordef square(x):return x * xif __name__ == "__main__":numbers = [1, 2, 3, 4, 5]tasks = []with ThreadPoolExecutor(max_workers=4) as executor:# 提交任务并将返回的 Future 对象添加到列表中for number in numbers:task = executor.submit(square, number)tasks .append(task)# 等待 ThreadPoolExecutor 线程池中的所有任务完成(调用result时会阻塞,直到任务完成,遍历已完成的任务并获取结果)for task in tasks:result = tasks.result() print("Result:", result)
上面例子中,submit()
方法用于异步提交单个任务。它接受一个可调用对象(如函数)和可调用对象的参数,map()
方法用于批量执行任务。它接受一个可调用对象(如函数)和一个可迭代对象(如列表)。