当前位置: 首页 > news >正文

Python使用多线程和异步调用

概述

在 Python 中,多线程和异步调用是处理并发任务的两种常用方式,适用于不同场景。

多线程(threading 模块)

多线程适合处理 I/O 密集型任务(如网络请求、文件读写),因为这类任务大部分时间在等待,线程可以在等待时切换到其他任务。

import threading
import timedef task(name, delay):"""线程执行的任务"""print(f"任务 {name} 开始")time.sleep(delay)  # 模拟I/O操作(如网络请求)print(f"任务 {name} 完成")# 创建线程
t1 = threading.Thread(target=task, args=("A", 2))
t2 = threading.Thread(target=task, args=("B", 3))# 启动线程
t1.start()
t2.start()# 等待所有线程完成
t1.join()
t2.join()print("所有任务完成")

特点

  • 优势:适合 I/O 密集型任务,线程切换开销小。
  • 限制:受 GIL(全局解释器锁)影响,CPU 密集型任务(如大量计算)无法真正并行,多线程可能比单线程更慢。
  • 适用场景:爬虫、API 调用、文件读写等。

线程池(ThreadPoolExecutor)

在 Python 中,线程池(ThreadPoolExecutor)是管理线程的高效方式,它可以预先创建一定数量的线程,避免频繁创建和销毁线程带来的开销,特别适合处理大量短期的 I/O 密集型任务(如网络请求、文件读写等)。

ThreadPoolExecutor 位于 concurrent.futures 模块中,使用起来非常简洁。

基本使用步骤

  1. 导入 ThreadPoolExecutor 类
  2. 创建线程池实例,指定最大线程数
  3. 提交任务到线程池(使用 submit() 或 map() 方法)
  4. 获取任务结果(可选)
  5. 关闭线程池(通常使用 with 语句自动管理)

示例 1:使用 submit() 提交单个任务

import time
from concurrent.futures import ThreadPoolExecutordef task(task_id, sleep_time):"""线程执行的任务:休眠指定时间后返回结果"""print(f"任务 {task_id} 开始执行,将休眠 {sleep_time} 秒")time.sleep(sleep_time)  # 模拟I/O操作result = f"任务 {task_id} 完成,休眠了 {sleep_time} 秒"return resultdef main():# 创建线程池,最大线程数为3with ThreadPoolExecutor(max_workers=3) as executor:# 提交3个任务到线程池futures = [executor.submit(task, 1, 2),  # 任务1,休眠2秒executor.submit(task, 2, 3),  # 任务2,休眠3秒executor.submit(task, 3, 1)   # 任务3,休眠1秒]# 获取所有任务的结果for future in futures:print(future.result())  # result()方法会阻塞直到任务完成if __name__ == "__main__":start_time = time.time()main()print(f"总耗时:{time.time() - start_time:.2f}秒")

运行结果说明:

  • 3 个任务并发执行,总耗时接近最长任务的耗时(3 秒)
  • with 语句会自动关闭线程池,无需手动调用 shutdown()

示例 2:使用 map() 批量处理任务

当需要对多个参数执行相同任务时,map() 方法更简洁:

import time
from concurrent.futures import ThreadPoolExecutordef process_item(item):"""处理单个项目的函数"""item_id, sleep_time = itemprint(f"处理项目 {item_id},休眠 {sleep_time} 秒")time.sleep(sleep_time)return f"项目 {item_id} 处理完成"def main():# 待处理的项目列表items = [(1, 2), (2, 3), (3, 1), (4, 2)]# 创建线程池,最大线程数为2with ThreadPoolExecutor(max_workers=2) as executor:# 使用map批量处理任务,返回结果顺序与输入顺序一致results = executor.map(process_item, items)# 遍历结果for result in results:print(result)if __name__ == "__main__":start_time = time.time()main()print(f"总耗时:{time.time() - start_time:.2f}秒")

map() 特点:

  • 结果返回顺序与输入列表顺序一致
  • 无需手动收集结果,直接迭代即可

示例 3:处理异常

线程池中的任务异常需要在获取结果时捕获:

import time
from concurrent.futures import ThreadPoolExecutor, as_completeddef risky_task(task_id):"""可能抛出异常的任务"""print(f"任务 {task_id} 开始执行")if task_id == 2:raise ValueError(f"任务 {task_id} 发生错误")time.sleep(1)return f"任务 {task_id} 成功完成"def main():with ThreadPoolExecutor(max_workers=2) as executor:futures = [executor.submit(risky_task, i) for i in range(1, 4)]# 使用as_completed获取已完成的任务(顺序不确定)for future in as_completed(futures):try:result = future.result()print(result)except ValueError as e:print(f"捕获到异常:{e}")if __name__ == "__main__":main()

as_completed() 特点:

  • 按任务完成顺序返回结果(与提交顺序可能不同)
  • 便于实时处理已完成的任务

线程池关键参数与方法

1.max_workers:线程池最大线程数

  • 对于 I/O 密集型任务,通常设置为 CPU核心数 * 5 左右
  • 对于 CPU 密集型任务,建议设置为 CPU核心数 + 1

2.常用方法:

  • submit(func, *args, **kwargs):提交单个任务,返回 Future 对象
  • map(func, *iterables):批量提交任务,返回结果迭代器
  • shutdown(wait=True):关闭线程池,wait=True 表示等待所有任务完成

3.Future 对象方法:

  • result(timeout=None):获取任务结果,可设置超时时间
  • add_done_callback(fn):任务完成后执行回调函数
  • cancel():取消未执行的任务

适用场景

  • 网络爬虫(批量请求网页)
  • API 接口测试(并发调用多个接口)
  • 日志处理(批量读取多个日志文件)
  • 任何需要并发处理的 I/O 密集型任务

线程池避免了频繁创建线程的开销,同时通过限制最大线程数防止系统资源耗尽,是 Python 并发编程中非常实用的工具。

异步调用(asyncio 模块)

异步编程通过 事件循环 实现并发,更适合处理 高并发 I/O 任务(如大量网络请求),效率通常高于多线程。

import asyncio
import timeasync def task(name, delay):"""异步任务(必须用async定义)"""print(f"任务 {name} 开始")# 模拟I/O操作(必须用await调用异步函数)await asyncio.sleep(delay)print(f"任务 {name} 完成")async def main():# 创建任务列表tasks = [asyncio.create_task(task("A", 2)),asyncio.create_task(task("B", 3))]# 等待所有任务完成await asyncio.gather(*tasks)# 启动事件循环
asyncio.run(main())
print("所有任务完成")

关键概念

  • async:定义异步函数,函数返回值为协程(coroutine)。
  • await:暂停当前协程,等待异步操作完成(只能在异步函数中使用)。
  • 事件循环:管理所有协程的执行,决定何时切换任务。

特点

  • 优势:纯 Python 层面实现并发,切换开销极小,适合超高并发 I/O 任务。
  • 限制:需配合异步库(如 aiohttp 而非 requests),不适合 CPU 密集型任务。
  • 适用场景:高并发 API 服务、WebSocket 服务、大量网络请求等。
http://www.zskr.cn/news/5966.html

相关文章:

  • 基于MATLAB/Simulink的TI2000系列DSP模型设计
  • 挖矿木马病毒清理手册
  • Python常见函数和代码示例
  • keil5中stm32相关记录
  • centos7中安装protobuf-c
  • MyEMS:赋能每一个组织,成为自己的能源管理专家
  • Vue开发微信公众号上传图片
  • 栈的妙用:如何优雅地处理括号匹配难题 (C语言版)
  • 食品包装 AI 视觉检测技术:原理、优势与数据应用解析
  • 电流探头的常见应用场景
  • PC桌面应用开发选择
  • 无需复杂正则:SLS 新脱敏函数让隐私保护更简单高效
  • PLC结构化文本设计模式——适配器模式(Adapter Pattern)
  • 深入浅出 Java 多线程:从线程生命周期到并发安全
  • 实用指南:LINUX910 CENTOS8 新建虚拟机;重设root密码/时间同步
  • 零基础学习PYthon记录
  • Grafana 中文入门教程 | 构建你的第一个仪表盘
  • Topaz Photo AI Pro 4.0.4 AI图片智能降噪
  • Edge浏览器网页长截图
  • C++多线程编程—线程控制、同步与互斥详解
  • mac 的任务栏 Windows-Style Taskbar For macOS
  • 快手Java一面
  • 想找Axure替代?这6个原型设计工具值得一试
  • 实用指南:javaweb HTML基本介绍/常见标签
  • 文档处理控件Aspose.Words教程:在 C# 中将 Markdown 转换为 PDF
  • docker容器mysql导入sql文件
  • IDE工具RAD Studio 13 Florence重磅发布:64 位 IDE + AI 组件全面升级!
  • 移动安全框架(MobSF)静态分析入门指南
  • CRMEB标准版PHP批量发货功能深度解析
  • 模型上下文协议(Model Context Protocol,MCP)