一、使用多线程(threading 模块)
解决思路:
- 导入
threading
模块。 - 定义一个函数,该函数将作为线程的执行体。
- 创建
Thread
对象,将函数作为参数传递给Thread
对象。 - 调用
start()
方法启动线程。
import threading
import time
def worker(num):
"""线程执行的函数"""
print(f"Thread {num} starting")
time.sleep(2) # 模拟耗时操作
print(f"Thread {num} finishing")
threads = []
for i in range(5):
t = threading.Thread(target=worker, args=(i,))
threads.append(t)
t.start()
for t in threads:
t.join() # 等待所有线程完成
代码解释:
import threading
导入 Python 的标准库中的threading
模块,用于创建和管理线程。def worker(num):
定义了一个函数,这个函数将作为线程的执行体,它接收一个参数num
作为线程的编号。time.sleep(2)
模拟了一个耗时的操作,这里线程会暂停 2 秒钟。threads = []
创建一个空列表用于存储线程对象。for i in range(5):
循环创建 5 个线程。t = threading.Thread(target=worker, args=(i,))
创建一个Thread
对象,将worker
函数作为目标函数,args=(i,)
为函数传递参数。t.start()
启动线程。t.join()
确保主线程等待子线程完成。
二、使用多进程(multiprocessing 模块)
解决思路:
- 导入
multiprocessing
模块。 - 定义一个函数,该函数将作为进程的执行体。
- 创建
Process
对象,将函数作为参数传递给Process
对象。 - 调用
start()
方法启动进程。
import multiprocessing
import time
def worker(num):
"""进程执行的函数"""
print(f"Process {num} starting")
time.sleep(2) # 模拟耗时操作
print(f"Process {num} finishing")
processes = []
if __name__ == "__main__":
for i in range(5):
p = multiprocessing.Process(target=worker, args=(i,))
processes.append(p)
p.start()
for p in processes:
p.join() # 等待所有进程完成
代码解释:
import multiprocessing
导入 Python 的标准库中的multiprocessing
模块,用于创建和管理进程。def worker(num):
定义了一个函数,这个函数将作为进程的执行体,它接收一个参数num
作为进程的编号。time.sleep(2)
模拟了一个耗时的操作,这里进程会暂停 2 秒钟。processes = []
创建一个空列表用于存储进程对象。for i in range(5):
循环创建 5 个进程。p = multiprocessing.Process(target=worker, args=(i,))
创建一个Process
对象,将worker
函数作为目标函数,args=(i,)
为函数传递参数。p.start()
启动进程。p.join()
确保主进程等待子进程完成。
三、使用协程(asyncio 模块)
解决思路:
- 导入
asyncio
模块。 - 定义一个异步函数,使用
async def
关键字。 - 在异步函数中使用
await
关键字等待异步操作完成。 - 使用
asyncio.run()
函数运行异步函数。
import asyncio
async def worker(num):
"""协程执行的函数"""
print(f"Coroutine {num} starting")
await asyncio.sleep(2) # 模拟耗时操作
print(f"Coroutine {num} finishing")
async def main():
tasks = []
for i in range(5):
tasks.append(worker(i))
await asyncio.gather(*tasks)
if __name__ == "__main__":
asyncio.run(main())
代码解释:
import asyncio
导入 Python 的标准库中的asyncio
模块,用于实现异步编程。async def worker(num):
定义了一个异步函数,使用async
关键字表示该函数是一个协程。await asyncio.sleep(2)
模拟一个耗时的异步操作,使用await
关键字等待操作完成。async def main():
定义了一个主协程,用于管理多个协程任务。tasks = []
创建一个任务列表。for i in range(5):
循环创建 5 个协程任务并添加到任务列表中。await asyncio.gather(*tasks)
并发执行所有任务并等待它们完成。asyncio.run(main())
运行主协程。
四、使用线程池(concurrent.futures 模块)
解决思路:
- 导入
concurrent.futures
模块。 - 使用
ThreadPoolExecutor
创建一个线程池。 - 定义一个函数,该函数将作为线程的执行体。
- 调用
submit()
方法将任务提交到线程池。
import concurrent.futures
import time
def worker(num):
"""线程池中的线程执行的函数"""
print(f"Thread pool worker {num} starting")
time.sleep(2) # 模拟耗时操作
print(f"Thread pool worker {num} finishing")
if __name__ == "__main__":
with concurrent.futures.ThreadPoolExecutor(max_workers=5) as executor:
futures = [executor.submit(worker, i) for i in range(5)]
for future in concurrent.futures.as_completed(futures):
future.result()
代码解释:
import concurrent.futures
导入 Python 的concurrent.futures
模块,用于创建和管理线程池。def worker(num):
定义了一个函数,作为线程池中的线程执行体。with concurrent.futures.ThreadPoolExecutor(max_workers=5) as executor:
创建一个最大工作线程数为 5 的线程池。executor.submit(worker, i)
将任务提交到线程池,worker
为任务函数,i
为参数。concurrent.futures.as_completed(futures)
等待所有任务完成,并获取它们的结果。
五、使用进程池(concurrent.futures 模块)
解决思路:
- 导入
concurrent.futures
模块。 - 使用
ProcessPoolExecutor
创建一个进程池。 - 定义一个函数,该函数将作为进程的执行体。
- 调用
submit()
方法将任务提交到进程池。
import concurrent.futures
import time
def worker(num):
"""进程池中的进程执行的函数"""
print(f"Process pool worker {num} starting")
time.sleep(2) # 模拟耗时操作
print(f"Process pool worker {num} finishing")
if __name__ == "__main__":
with concurrent.futures.ProcessPoolExecutor(max_workers=5) as executor:
futures = [executor.submit(worker, i) for i in range(5)]
for future in concurrent.futures.as_completed(futures):
future.result()
代码解释:
import concurrent.futures
导入 Python 的concurrent.futures
模块,用于创建和管理进程池。def worker(num):
定义了一个函数,作为进程池中的进程执行体。with concurrent.futures.ProcessPoolExecutor(max_workers=5) as executor:
创建一个最大工作进程数为 5 的进程池。executor.submit(worker, i)
将任务提交到进程池,worker
为任务函数,i
为参数。concurrent.futures.as_completed(futures)
等待所有任务完成,并获取它们的结果。
根据不同的应用场景和性能要求,可以选择不同的并发编程方式:
- 多线程适合 I/O 密集型操作,因为 Python 的全局解释器锁(GIL)会限制 CPU 密集型操作的性能提升。
- 多进程适合 CPU 密集型操作,因为每个进程都有自己的 GIL。
- 协程适合大量的 I/O 操作,尤其是网络 I/O,因为它使用单线程,避免了线程切换的开销。
- 线程池和进程池方便管理和复用线程和进程资源,适用于任务数量较多的情况。