深入理解Python中的并发与异步的结合使用
在上一篇文章中,我们讨论了异步编程中的性能优化技巧,并简单介绍了trio和curio库。今天,我们将深入探讨如何将并发编程与异步编程结合使用,并详细讲解如何利用trio和curio库优化异步编程中的性能。
文章目录
- 并发与异步编程的区别与联系
- 并发编程与异步编程的优缺点
- 并发编程
- 异步编程
- 如何在同一个程序中同时使用 `threading`、`multiprocessing` 和 `asyncio`
- 使用 `threading` 和 `asyncio`
- 深入使用 `trio` 库
- 基本使用
- 高级功能:取消与超时
- 深入使用 `curio` 库
- 基本使用
- 高级功能:任务取消与超时
- 性能优化技巧
- 结语
并发与异步编程的区别与联系
并发编程和异步编程都是处理多任务的有效手段,但它们的实现方式和适用场景有所不同:
- 并发编程:通过线程或进程来同时执行多个任务,适用于CPU密集型任务;
- 异步编程:通过事件循环和协程来调度任务,适用于I/O密集型任务。
结合使用并发和异步编程,可以同时处理CPU密集型和I/O密集型任务,提升程序整体性能。
并发编程与异步编程的优缺点
并发编程
- 优点:
- 可以充分利用多核CPU的优势,提高程序的执行效率;
- 适用于需要大量计算的任务,例如数据处理、图像处理等。
- 缺点:
- 线程和进程的管理和调度较为复杂,需要处理同步、锁等问题;
- 创建和销毁线程或进程会有一定的开销。
异步编程
- 优点:
- 适用于I/O密集型任务,可以在等待I/O操作完成时执行其他任务,提高资源利用率;
- 代码更加简洁,逻辑清晰。
- 缺点:
- 仅能在单线程中运行,不能利用多核CPU的优势;
- 对于CPU密集型任务效果不佳。
如何在同一个程序中同时使用 threading、multiprocessing 和 asyncio
在同一个程序中,我们可以利用 threading 和 multiprocessing 提供并发能力,同时使用 asyncio 实现异步I/O操作:
使用 threading 和 asyncio
import asyncio
import threadingasync def async_task():print("Starting async task")await asyncio.sleep(2)print("Async task completed")def sync_task(loop):print("Starting sync task")loop.run_until_complete(async_task())print("Sync task completed")loop = asyncio.get_event_loop()
thread = threading.Thread(target=sync_task, args=(loop,))
thread.start()
thread.join()
使用 multiprocessing 和 asyncio
import asyncio
import multiprocessingasync def async_task():print("Starting async task")await asyncio.sleep(2)print("Async task completed")def sync_task():loop = asyncio.new_event_loop()asyncio.set_event_loop(loop)loop.run_until_complete(async_task())if __name__ == "__main__":process = multiprocessing.Process(target=sync_task)process.start()process.join()
深入使用 trio 库
trio对异步编程提供了更友好的API,以及更加健壮的错误处理机制;它简化了异步编程的许多复杂性,特别是对于需要多个并发任务的场景:
基本使用
import trio
import asksasync def fetch(url):response = await asks.get(url)return response.textasync def main():urls = ['http://example.com', 'http://example.org', 'http://example.net']async with trio.open_nursery() as nursery:for url in urls:nursery.start_soon(fetch, url)trio.run(main)
高级功能:取消与超时
在trio中,可以轻松地对任务进行取消和超时操作:
import trioasync def long_running_task():try:print("Task started")await trio.sleep(10)print("Task completed")except trio.Cancelled:print("Task was cancelled")async def main():async with trio.open_nursery() as nursery:nursery.start_soon(long_running_task)await trio.sleep(5)nursery.cancel_scope.cancel()trio.run(main)
异常处理与重试机制
import trio
import asksasync def fetch_with_retry(url, retries=3):for attempt in range(retries):try:response = await asks.get(url)return response.textexcept Exception as e:print(f"Attempt {attempt + 1} failed: {e}")await trio.sleep(2)raise Exception(f"Failed to fetch {url} after {retries} attempts")async def main():urls = ['http://example.com', 'http://example.org', 'http://example.net']async with trio.open_nursery() as nursery:for url in urls:nursery.start_soon(fetch_with_retry, url)trio.run(main)
深入使用 curio 库
curio 是另一个异步编程库,主要强调简单性和高性能,适用于需要低延迟和高吞吐量的场景:
基本使用
import curio
import httpxasync def fetch(url):async with httpx.AsyncClient() as client:response = await client.get(url)return response.textasync def main():urls = ['http://example.com', 'http://example.org', 'http://example.net']tasks = [fetch(url) for url in urls]results = await curio.gather(tasks)for result in results:print(result[:100])if __name__ == "__main__":curio.run(main)
高级功能:任务取消与超时
curio 和trio一样提供了强大的任务管理功能,其中也包括对任务取消和超时操作的处理:
import curioasync def long_running_task():try:print("Task started")await curio.sleep(10)print("Task completed")except curio.CancelledError:print("Task was cancelled")async def main():task = await curio.spawn(long_running_task)await curio.sleep(5)await task.cancel()if __name__ == "__main__":curio.run(main)
使用信号与事件进行任务同步
import curioasync def producer(event):print("Producer sleeping")await curio.sleep(5)print("Producer setting event")await event.set()async def consumer(event):print("Consumer waiting for event")await event.wait()print("Consumer got event")async def main():event = curio.Event()await curio.gather(producer(event), consumer(event))if __name__ == "__main__":curio.run(main)
性能优化技巧
通过结合并发和异步编程技术,以及使用trio和curio库,我们可以在处理大量I/O密集型任务时获得显著的性能提升,以下是我在工作中常用的一些性能优化技巧:
- 限制并发请求数量:使用信号量(semaphore)限制同时进行的请求数量,防止过多的请求导致系统资源枯竭;
- 分块处理任务:将任务划分为多个块,分别进行处理,避免一次性处理大量任务导致的性能问题;
- 使用连接池:复用连接,减少连接建立和销毁的开销;
- 合理设置超时时间:为每个请求设置合理的超时时间,防止由于某些请求超时导致整个任务的延迟;
- 异步I/O操作:尽量使用异步I/O操作,避免阻塞主线程。
结语
通过本文的介绍,我们深入学习了如何将并发编程与异步编程结合使用,以最大化程序的性能和效率。结合使用 threading、multiprocessing 和 asyncio 可以同时处理CPU密集型和I/O密集型任务,提升程序整体性能,希望这些技巧能帮助你在实际项目中编写出高效、稳定的代码!
如果你对计算机相关技术有更多的兴趣,想要持续的探索,请关注我的公众号哟!

相关文章:
深入理解Python中的并发与异步的结合使用
在上一篇文章中,我们讨论了异步编程中的性能优化技巧,并简单介绍了trio和curio库。今天,我们将深入探讨如何将并发编程与异步编程结合使用,并详细讲解如何利用trio和curio库优化异步编程中的性能。 文章目录 并发与异步编程的区…...
如何将 ChatGPT 集成到你的应用中
在当今快速发展的技术环境中,将人工智能聊天解决方案集成到你的应用程序中可以显著提升用户体验和参与度。OpenAI 的 ChatGPT 以其对话能力和高级语言理解而闻名,对于希望在其应用程序中实现智能聊天功能的开发人员来说是一个绝佳的选择。那我们今天就来…...
在 Swift 中,UILabel添加点击事件的方法
在 Swift 中,可以使用 UITapGestureRecognizer 给 UILabel 添加点击事件。以下是一个详细的步骤和示例代码: 1. 创建 UILabel 并添加到视图 在 Storyboard 或代码中创建一个 UILabel 并将其添加到视图中。 2. 启用 UILabel 的用户交互 默认情况下&am…...
indexedDB---掌握浏览器内建数据库的基本用法
1.认识indexedDB IndexedDB 是一个浏览器内建的数据库,它可以存放对象格式的数据,类似本地存储localstore,但是相比localStore 10MB的存储量,indexedDB可存储的数据量远超过这个数值,具体是多少呢? 默认情…...
【css】如何修改input选中历史选项后,自动填充的蓝色背景色
自动填充前: 自动填充后: 解决办法 方法一:设置背景透明(通过拉长过渡时间,和延迟过渡开始时间,掩盖input自动填充背景颜色) PS:注意,这个过渡效果会在你的delay tim…...
红队内网攻防渗透:内网渗透之内网对抗:网络通讯篇防火墙组策略入站和出站规则单层双层C2正反向上线解决方案
红队内网攻防渗透 1. 内网网络通讯1.1 防火墙策略-入站规则&出站规则&自定义1.1.1 防火墙默认入站&出站策略1.1.2 防火墙自定义入站&出站策略1.1.3 内网域防火墙同步策略1.2 防火墙限制1.2.1 防火墙限制端口1.2.2 防火墙限制协议1.2.2.1 防火墙协议入站限制1.2…...
linux 查看进程启动方式
目录 如果是systemd管理的服务怎么快速找到对应的服务器呢 什么是CGroup 查找进程对应的systemd服务 方法一:查看 /proc//cgroup 文件 方法二:使用 ps 命令结合 --cgroup 选项 方法三:systemd-cgls 关于 system.slice 与 user.slice …...
基于Java实训中心管理系统设计和实现(源码+LW+调试文档+讲解等)
💗博主介绍:✌全网粉丝10W,CSDN作者、博客专家、全栈领域优质创作者,博客之星、平台优质作者、专注于Java、小程序技术领域和毕业项目实战✌💗 🌟文末获取源码数据库🌟 感兴趣的可以先收藏起来,…...
第2章 Android应用的界面编程
🌈个人主页:小新_- 🎈个人座右铭:“成功者不是从不失败的人,而是从不放弃的人!”🎈 🎁欢迎各位→点赞👍 收藏⭐️ 留言📝 🏆所属专栏࿱…...
springboot学习-图灵课堂-最详细学习
springboot-repeat springBoot学习代码说明为什么java -jar springJar包后项目就可以启动 配置文件介绍 springBoot学习 依赖引入 <properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><maven.compiler.target>8</mav…...
Total CAD Converter与Total Excel Converter软件分享
1.软件介绍 Total CAD Converter Total CAD Converter 是一款功能强大的工具,能够将 CAD 文件转换为多种格式,如 PDF、TIFF、JPEG、BMP、WMF、PNG、DXF、BMP、CGM、HPGL、SVG、PS 和 SWF 等。其支持的源格式丰富多样,包括 dxf、dwg、dwf、d…...
【2024最新华为OD-C/D卷试题汇总】[支持在线评测] 启动多任务排序(200分) - 三语言AC题解(Python/Java/Cpp)
🍭 大家好这里是清隆学长 ,一枚热爱算法的程序员 ✨ 本系列打算持续跟新华为OD-C/D卷的三语言AC题解 💻 ACM银牌🥈| 多次AK大厂笔试 | 编程一对一辅导 👏 感谢大家的订阅➕ 和 喜欢💗 📎在线评测链接 启动多任务排序(200分) 🌍 评测功能需要订阅专栏后私信联系…...
【会议征稿,JPCS出版】第三届电力系统与能源技术国际学术会议(ICPSET 2024,7月5-7)
第三届电力系统与能源技术国际学术会议(ICPSET 2024)将于2024年7月5-7日在杭州举办。由浙江水利水电学院电机产业学院主办,AEIC学术交流中心承办,湖州市南浔创新研究院、南浔区科技局(科协)协办 。会议主要…...
【机器学习300问】118、循环神经网络(RNN)的基本结构是怎样的?
将讲解循环神经网络RNN之前,我先抛出几个疑问:为什么发明循环神经网络?它的出现背景是怎样的?这些问题可以帮助我们更好的去理解RNN。下面我来逐一解答。 一、循环神经网络诞生的背景 循环神经网络(RNN)的…...
loveqq-framework 和 thymeleaf 整合遇到的 th:field 的坑,原来只有 spring 下才有效
相信大家在使用 thymeleaf 的时候,绝大部分都是和 springboot 一块儿使用的,所以 th:field 属性用的很舒服。 但实际上,th:field 只有在 spring 环境下下有用,单独的 thymeleaf 是不支持的! 为什么我知道呢ÿ…...
hugging face:大模型时代的github介绍
1. Hugging Face是什么: Hugging Face大模型时代的“github”,很多人有个这样的认知,但是我觉得不完全准确,他们相似的地方在于资源丰富,github有各种各样的软件代码和示例,但是它不是系统的,没…...
如何快速绘制logistic回归预测模型的ROC曲线?
临床预测模型,也是临床统计分析的一个大类,除了前期构建模型,还要对模型的预测能力、区分度、校准度、临床获益等方面展开评价,确保模型是有效的! 其中评价模型的好坏主要方面还是要看区分度和校准度,而区分…...
实现具有多个实现类的接口并为每个实现类定义一个名字的方法
在Java中,实现具有多个实现类的接口并为每个实现类定义一个名字的方法,可以通过使用工厂模式或服务定位器模式来完成。以下是使用工厂模式的一个示例: 定义接口和实现类 首先,定义一个接口和多个实现类: // 接口 publ…...
Linux解压缩命令
文章目录 前言1. tar - 打包和压缩文件2. gzip - 压缩文件3. gunzip - 解压缩gzip文件4. bzip2 - 压缩文件5. unzip - 解压缩zip文件6. zip - 压缩文件为zip格式7. 7z - 7-Zip压缩工具8. unrar - 解压缩RAR文件 前言 解压缩文件在Linux中是常见的任务,以下是一些常…...
如何在 Ubuntu 14.04 上使用 Iptables 实现基本防火墙模板
前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站。 简介 实施防火墙是保护服务器的重要步骤。其中很大一部分是决定强制执行对网络流量的限制的个别规则和策略。像 iptables 这样的防火墙…...
使用docker在3台服务器上搭建基于redis 6.x的一主两从三台均是哨兵模式
一、环境及版本说明 如果服务器已经安装了docker,则忽略此步骤,如果没有安装,则可以按照一下方式安装: 1. 在线安装(有互联网环境): 请看我这篇文章 传送阵>> 点我查看 2. 离线安装(内网环境):请看我这篇文章 传送阵>> 点我查看 说明:假设每台服务器已…...
Docker 离线安装指南
参考文章 1、确认操作系统类型及内核版本 Docker依赖于Linux内核的一些特性,不同版本的Docker对内核版本有不同要求。例如,Docker 17.06及之后的版本通常需要Linux内核3.10及以上版本,Docker17.09及更高版本对应Linux内核4.9.x及更高版本。…...
微信小程序之bind和catch
这两个呢,都是绑定事件用的,具体使用有些小区别。 官方文档: 事件冒泡处理不同 bind:绑定的事件会向上冒泡,即触发当前组件的事件后,还会继续触发父组件的相同事件。例如,有一个子视图绑定了b…...
Admin.Net中的消息通信SignalR解释
定义集线器接口 IOnlineUserHub public interface IOnlineUserHub {/// 在线用户列表Task OnlineUserList(OnlineUserList context);/// 强制下线Task ForceOffline(object context);/// 发布站内消息Task PublicNotice(SysNotice context);/// 接收消息Task ReceiveMessage(…...
在HarmonyOS ArkTS ArkUI-X 5.0及以上版本中,手势开发全攻略:
在 HarmonyOS 应用开发中,手势交互是连接用户与设备的核心纽带。ArkTS 框架提供了丰富的手势处理能力,既支持点击、长按、拖拽等基础单一手势的精细控制,也能通过多种绑定策略解决父子组件的手势竞争问题。本文将结合官方开发文档,…...
FastAPI 教程:从入门到实践
FastAPI 是一个现代、快速(高性能)的 Web 框架,用于构建 API,支持 Python 3.6。它基于标准 Python 类型提示,易于学习且功能强大。以下是一个完整的 FastAPI 入门教程,涵盖从环境搭建到创建并运行一个简单的…...
c++ 面试题(1)-----深度优先搜索(DFS)实现
操作系统:ubuntu22.04 IDE:Visual Studio Code 编程语言:C11 题目描述 地上有一个 m 行 n 列的方格,从坐标 [0,0] 起始。一个机器人可以从某一格移动到上下左右四个格子,但不能进入行坐标和列坐标的数位之和大于 k 的格子。 例…...
剑指offer20_链表中环的入口节点
链表中环的入口节点 给定一个链表,若其中包含环,则输出环的入口节点。 若其中不包含环,则输出null。 数据范围 节点 val 值取值范围 [ 1 , 1000 ] [1,1000] [1,1000]。 节点 val 值各不相同。 链表长度 [ 0 , 500 ] [0,500] [0,500]。 …...
基于matlab策略迭代和值迭代法的动态规划
经典的基于策略迭代和值迭代法的动态规划matlab代码,实现机器人的最优运输 Dynamic-Programming-master/Environment.pdf , 104724 Dynamic-Programming-master/README.md , 506 Dynamic-Programming-master/generalizedPolicyIteration.m , 1970 Dynamic-Programm…...
Netty从入门到进阶(二)
二、Netty入门 1. 概述 1.1 Netty是什么 Netty is an asynchronous event-driven network application framework for rapid development of maintainable high performance protocol servers & clients. Netty是一个异步的、基于事件驱动的网络应用框架,用于…...
