苦练 Python 第 68 天:并发狂飙!concurrent 模块让你 CPU 原地起飞

前言

大家好,我是 倔强青铜三 。欢迎关注我,微信公众号: 倔强青铜三。点赞、收藏、关注,一键三连!

今天咱们来一起挖掘 Python 自带的 "并发神器" ------ concurrent 模块,让你的 CPU 性能瞬间拉满。

一、concurrent 模块登场的必要性

Python 中已经有了 threading 和 multiprocessing 这两个模块来处理多线程和多进程相关操作,但是 concurrent 模块的出现有其独特的优势:

  • 高层抽象,简化开发 :它在 threading 和 multiprocessing 基础之上提供了更高层次的抽象,使得开发者可以更加方便地构建并行程序,无需过多关注底层细节。
  • 统一接口,便于切换 :通过 concurrent.futures 模块中的 Executor 接口,无论是使用线程池还是进程池,都有一致的接口和使用方式,方便在不同场景下灵活切换。
  • 强大功能,提升效率 :提供了诸如 Future 对象等强大的功能,方便对异步操作的结果进行管理和监控,有效提升并发编程的效率和可维护性。

concurrent 模块常用 API 一览表

API 作用 关键入参 返回值
concurrent.futures.ThreadPoolExecutor 创建线程池执行器 max_workers 最大工作线程数等 Future 对象
concurrent.futures.ProcessPoolExecutor 创建进程池执行器 max_workers 最大工作进程数等 Future 对象
concurrent.futures.Future 表示异步执行的操作 无 异步操作的结果

二、快速体验 ThreadPoolExecutor 并发下载

python 复制代码
# demo_thread_pool.py
import concurrent.futures
import urllib.request
import time

# 模拟下载任务
def download_url(url):
    try:
        with urllib.request.urlopen(url, timeout=5) as response:
            content = response.read()
            return len(content)
    except Exception as e:
        return str(e)

urls = [
    "https://www.baidu.com",
    "https://www.qq.com",
    "https://www.taobao.com",
    "https://www.jd.com",
    "https://www.sina.com.cn"
]

# 单线程下载
start_time = time.time()
for url in urls:
    print(download_url(url))
print("单线程下载耗时:", time.time() - start_time)

# 线程池下载
with concurrent.futures.ThreadPoolExecutor(max_workers=3) as executor:
    start_time = time.time()
    futures = {executor.submit(download_url, url): url for url in urls}
    for future in concurrent.futures.as_completed(futures):
        url = futures[future]
        try:
            result = future.result()
            print(f"{url}: {result}")
        except Exception as e:
            print(f"{url} 生成了异常: {e}")
    print("线程池下载耗时:", time.time() - start_time)

运行效果示例(因网络等因素实际结果可能不同):

arduino 复制代码
单线程下载耗时: 0.4107840061187744
https://www.baidu.com: 29506
https://www.taobao.com: 83249
https://www.qq.com: 122185
https://www.jd.com: 177956
https://www.sina.com.cn: 397807
线程池下载耗时: 0.136491060256958

三、ProcessPoolExecutor 处理 CPU 密集型任务

python 复制代码
# demo_process_pool.py
import concurrent.futures
import time

# CPU 密集型任务
def cpu_intensive_task(x):
    result = 0
    for i in range(10**7):
        result += i ** x
    return result

data = [2, 3, 4, 5, 6, 7, 8, 9]

# 单进程处理
start_time = time.time()
for num in data:
    print(cpu_intensive_task(num))
print("单进程处理耗时:", time.time() - start_time)

# 进程池处理
with concurrent.futures.ProcessPoolExecutor() as executor:
    start_time = time.time()
    futures = {executor.submit(cpu_intensive_task, num): num for num in data}
    for future in concurrent.futures.as_completed(futures):
        num = futures[future]
        try:
            result = future.result()
            print(f"任务 {num} 的结果:{result}")
        except Exception as e:
            print(f"任务 {num} 生成了异常: {e}")
    print("进程池处理耗时:", time.time() - start_time)

运行效果示例(具体数值和耗时根据机器性能而定):

erlang 复制代码
单进程处理耗时: 45.6789
任务 2 的结果: 333333330000000
任务 3 的结果: 4000000060000000
...
进程池处理耗时: 12.3456

四、Future 对象掌控异步操作

python 复制代码
# demo_future.py
import concurrent.futures
import time

def task(n):
    time.sleep(n)
    return f"任务完成,休眠了 {n} 秒"

# 创建线程池执行器
executor = concurrent.futures.ThreadPoolExecutor(max_workers=2)

# 提交任务并获取 Future 对象
future1 = executor.submit(task, 2)
future2 = executor.submit(task, 3)

print("检查 task1 是否完成:", future1.done())  # False
print("检查 task2 是否完成:", future2.done())  # False

time.sleep(3)

print("检查 task1 是否完成:", future1.done())  # True
print("检查 task2 是否完成:", future2.done())  # True

print("task1 的结果:", future1.result())  # 获取任务结果
print("task2 的结果:", future2.result())

executor.shutdown()  # 关闭执行器

运行效果:

python 复制代码
检查 task1 是否完成: False
检查 task2 是否完成: False
检查 task1 是否完成: True
检查 task2 是否完成: True
task1 的结果: 任务完成,休眠了 2 秒
task2 的结果: 任务完成,休眠了 3 秒

五、如何选择合适的并发工具

任务类型判断

如果是 I/O 密集型任务,比如大量网络请求、文件操作等,使用 ThreadPoolExecutor 更合适。

因为它可以充分利用线程在等待 I/O 操作期间切换到其他任务执行的优势,提高整体效率。

而如果是 CPU 密集型任务,如复杂的数学计算、数据处理等,则更适合使用 ProcessPoolExecutor。

因为多进程可以突破 Python 的全局解释器锁(GIL)限制,真正实现多个 CPU 核心并行计算。

资源限制考虑

根据系统的线程和进程资源限制,合理设置 max_workers 参数。

线程太多可能会导致频繁的线程切换开销,进程太多则会占用过多的内存和系统资源。

结果处理需求

如果需要对异步操作的结果进行复杂的处理和监控,Future 对象提供了丰富的接口和方法,可以方便地获取任务状态、结果、异常等信息。

无论使用线程池还是进程池,都可以借助 Future 来更好地管理和协调并发任务。


小结

武器 用途 一句话记忆
ThreadPoolExecutor 处理 I/O 密集型任务 I/O 密集型,线程池更高效
ProcessPoolExecutor 处理 CPU 密集型任务 CPU 密集型,进程池突破 GIL
Future 管理异步操作 异步操作好帮手
零依赖 官方自带 开箱即用

最后感谢阅读!欢迎关注我,微信公众号: 倔强青铜三 。
点赞、收藏、关注 ,一键三连!!

欢迎 点击 👍喜欢作者 按钮进行 打赏💰💰,请我喝一杯咖啡☕️!

相关推荐
2501_938140071 小时前
做内容很省心,2026好用AI笔记,支持抖音小红书视频无水印保存
人工智能
sell-cloud4 小时前
Prompt Engineering要凉了?Fable 5.5能“猜“意图,但银行正在封杀AI Agent——企业AI的真正护城河是什么
人工智能·prompt
Navicat中国6 小时前
Navicat 18 内置 AI 助手让数据库开发从繁琐操作迈向智能协作
大数据·人工智能·数据库开发
4SAPI6 小时前
多模型请求路由怎么设计?成本、速度和能力如何平衡
人工智能·python·gateway·php
魔乐社区6 小时前
翼芯・智算测试与适配优化专区,让国产算力“选得准、跑得通、用得好“
人工智能·开源·大模型
XCDoris8 小时前
郴州logo设计机构
大数据·人工智能·python
Goboy8 小时前
一个人带三个Agent,我用全新TRAE从0到1搭了个资讯周刊站
人工智能·trae
俊哥V8 小时前
每日 AI 研究简报 · 2026-10-19
人工智能·ai
AI_AGENT_DEV_AI9 小时前
AI英语教培智能体的开发
人工智能
物联网软硬件开发-轨物科技9 小时前
【技术白皮书】光伏清检一体化机器人系统解决方案技术白皮书
大数据·运维·网络·人工智能·机器人