010.理解异步性

2024-05-15 16:28
文章标签 理解 异步 010

本文主要是介绍010.理解异步性,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

异步消息传递是响应式系统的一个关键特性。但到底是什么异步性,为什么它对响应式应用程序如此重要?我们的人生注定在许多异步任务中。你可能没有意识到,但你的日常活动如果它们本质上不是异步的,那就太烦人了。要理解什么是异步,首先需要理解非异步执行或同步执行。

同步执行意味着您必须等待一个任务完成,然后才能继续执行下一个任务。同步执行的一个现实例子发生在快餐店:你走向柜台的工作人员,在店员等待的时候决定要点什么,点你的食物,一直等到饭菜准备好。店员等着你把钱交出来,然后给你食物。只有这样,你才能继续下一个任务,去你的桌子吃饭。这个序列如图1.14所示。
在这里插入图片描述
图1.14同步点餐,每一步都必须完成后才能进入下一步

这种类型的序列感觉像是在浪费时间(或者,更好地说,是在浪费资源),所以想象一下当你为应用程序做同样的事情时,你的应用程序会有什么感觉。下一节将对此进行演示。

一、这都是关于资源的使用
想象一下你的生活会是什么样子,如果在你做其它事情之前,你必须等待每一个操作完成,此时,那会有多少资源处于等待。同样的问题也与计算机科学相关:

writeResult = LongDiskWrite();
response = LongWebRequest();
entities = LongDatabaseQuery();

在这个同步代码片段中,LongDatabaseQuery将不会开始执行,直到LongWebRequest和LongDiskWrite完成。在执行每个方法的过程中,调用线程被阻塞,它所拥有的资源实际上被浪费了,不能用于服务其他请求或处理其他事件。如果这种情况发生在UI线程上,那么应用程序将看起来冻结,直到执行完成。如果这种情况发生在服务器应用程序上,那么在某个时刻,您可能会用完可用线程,并且请求将开始被拒绝。在这两种情况下,应用程序都停止响应。

运行前面的代码片段所需的总时间如下:

total_time = LongDiskWritetime + LongWebRequesttime + LongDatabaseQuerytime

总完成时间是其组成部分的完成时间之和。如果您可以在不等待上一个操作完成的情况下启动一个操作,则可以更好地使用您的资源。这就是异步执行的作用。

异步执行意味着一个操作已经启动,但它的执行是在后台进行的,并且调用者没有被阻止。相反,当操作完成时,会通知调用方。在这段时间里,调用者可以继续做有用的工作。

在点餐示例中,异步方法类似于坐在桌子旁由服务员服务。首先,你坐在桌子旁,服务员来递给你菜单,然后离开。当你决定点什么时,服务员仍然可以为其他顾客服务。当你决定了要什么餐后,服务员会回来帮你点餐。在准备食物的同时,你可以自由聊天、使用手机或欣赏风景。你没有被阻拦(服务员也没有)。当食物准备好后,服务员把它端到你的桌子上,然后回去为其他顾客服务,直到你要求结账并付款。

该模型是异步的:任务并发执行,执行的时间与请求的时间不同。这样,资源(例如
服务员)可以自由处理更多的要求。

异步执行发生在哪里?
在计算机程序中,我们可以区分两种类型的异步操作:基于cpu的和基于I/ o的。
在基于cpu的操作中,异步代码在另一个线程上运行当另一个线程的执行结束时返回结果。
在基于I/O的操作中,操作是在I/O设备(如硬盘)上进行的驱动器或网络。在网络上,向另一台机器发出请求(通过使用TCP)或UDP或其他网络协议),以及机器上的操作系统何时收到信号由网络硬件发出的中断结果返回,则操作将完成。
在这两种情况下,调用线程都可以自由地执行其他任务并处理其他任务请求和事件。

异步运行代码的方法不止一种,这取决于所使用的语言。附录A展示了在c#中实现这一点的方法,并深入研究了每个比特和字节。现在,让我们看一个使用。net future实现的异步工作的例子——Task类:

上述代码片段的异步版本如下所示:

taskA = LongDiskWriteAsync();
taskB = LongWebRequestAsync();
taskC = LongDatabaseQueryAsync();
Task.WaitAll(taskA, taskB, taskC);

在这个版本中,每个方法都返回Task<T>。这个类表示一个正在后台执行的操作。当调用每个方法时,调用线程不会被阻塞,并且该方法会立即返回。然后在上一个方法仍在执行时调用下一个方法。当所有方法都被调用时,您可以使用Task来等待它们的完成。WaitAll方法,该方法获取任务和块的集合,直到所有任务和块都完成为止。另一种写法如下:

taskA = LongDiskWriteAsync();
taskB = LongWebRequestAsync();
taskC = LongDatabaseQueryAsync();
taskA.Wait();
taskB.Wait(); 
taskC.Wait();

这样,你会得到同样的结果;您等待每个任务完成(当它们仍在后台运行时)。如果在调用Wait方法时任务已经完成,它将立即返回。运行代码片段的异步版本所需的总时间如下:
total_time = MAX(LongDiskWritetime, LongWebRequesttime, LongDatabaseQuerytime)
因为所有方法都是并发运行的(甚至可能是并行运行的),所以运行代码所需的时间将是最长操作的时间。

二、Rx与异步编程

异步执行并不局限于仅通过使用Task<t>来处理。在附录A中,您将了解中使用的其他模式.NET Framework提供异步执行。

回顾IObservable,即时变变量的Rx表示,您可以使用它来表示任何异步模式,因此当异步执行完成(成功或出现错误)时,执行链将运行,并评估依赖关系。Rx提供了将各种类型的异步执行(如Task<T>)转换为IObservable<T>的方法。

例如,在Shoppy应用程序中,不仅当您的位置发生变化时,而且当您的连接状态变为在线时,您都希望获得新的折扣——例如,如果您的手机短时间失去信号,然后重新连接。对Shoppy web服务的调用是以异步方式完成的,当它完成时,您希望更新视图以显示新项目:

IObservable<Connectivity> myConnectivity=...
IObservable<IEnumerable<Discount>> newDiscounts =from connectivity in myConnectivitywhere connectivity == Connectivity.Onlinefrom discounts in GetDiscounts() //GetDiscounts返回一个任务,该任务已隐式转换为可观察项。select discounts;newDiscounts.Subscribe(discounts => RefreshView(discounts));//RefreshView显示折扣。
private Task<IEnumerable<Discount>> GetDiscounts()
{//Sends request to the server and receives the collection of discounts
}

在本例中,您将对myConnectivity可观察到的连接更改做出反应。每次连接发生变化时,您都会检查是否是因为您处于联机状态,如果是,则调用异步Get Discounts方法。方法执行完成后,您可以选择返回的结果。这个结果将被推送给从您的代码中创建的新折扣可观察的观察者。

——未完待续

译者:重庆教主(QQ23611316) 2024.05.14

网站:WPF中文网 wpfsoft.com

这篇关于010.理解异步性的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/992327

相关文章

Python 中的异步与同步深度解析(实践记录)

《Python中的异步与同步深度解析(实践记录)》在Python编程世界里,异步和同步的概念是理解程序执行流程和性能优化的关键,这篇文章将带你深入了解它们的差异,以及阻塞和非阻塞的特性,同时通过实际... 目录python中的异步与同步:深度解析与实践异步与同步的定义异步同步阻塞与非阻塞的概念阻塞非阻塞同步

Java 中实现异步的多种方式

《Java中实现异步的多种方式》文章介绍了Java中实现异步处理的几种常见方式,每种方式都有其特点和适用场景,通过选择合适的异步处理方式,可以提高程序的性能和可维护性,感兴趣的朋友一起看看吧... 目录1. 线程池(ExecutorService)2. CompletableFuture3. ForkJoi

Python异步编程中asyncio.gather的并发控制详解

《Python异步编程中asyncio.gather的并发控制详解》在Python异步编程生态中,asyncio.gather是并发任务调度的核心工具,本文将通过实际场景和代码示例,展示如何结合信号量... 目录一、asyncio.gather的原始行为解析二、信号量控制法:给并发装上"节流阀"三、进阶控制

Spring Boot 中正确地在异步线程中使用 HttpServletRequest的方法

《SpringBoot中正确地在异步线程中使用HttpServletRequest的方法》文章讨论了在SpringBoot中如何在异步线程中正确使用HttpServletRequest的问题,... 目录前言一、问题的来源:为什么异步线程中无法访问 HttpServletRequest?1. 请求上下文与线

在 Spring Boot 中使用异步线程时的 HttpServletRequest 复用问题记录

《在SpringBoot中使用异步线程时的HttpServletRequest复用问题记录》文章讨论了在SpringBoot中使用异步线程时,由于HttpServletRequest复用导致... 目录一、问题描述:异步线程操作导致请求复用时 Cookie 解析失败1. 场景背景2. 问题根源二、问题详细分

Java中将异步调用转为同步的五种实现方法

《Java中将异步调用转为同步的五种实现方法》本文介绍了将异步调用转为同步阻塞模式的五种方法:wait/notify、ReentrantLock+Condition、Future、CountDownL... 目录异步与同步的核心区别方法一:使用wait/notify + synchronized代码示例关键

springboot的调度服务与异步服务使用详解

《springboot的调度服务与异步服务使用详解》本文主要介绍了Java的ScheduledExecutorService接口和SpringBoot中如何使用调度线程池,包括核心参数、创建方式、自定... 目录1.调度服务1.1.JDK之ScheduledExecutorService1.2.spring

异步线程traceId如何实现传递

《异步线程traceId如何实现传递》文章介绍了如何在异步请求中传递traceId,通过重写ThreadPoolTaskExecutor的方法和实现TaskDecorator接口来增强线程池,确保异步... 目录前言重写ThreadPoolTaskExecutor中方法线程池增强总结前言在日常问题排查中,

深入理解Apache Airflow 调度器(最新推荐)

《深入理解ApacheAirflow调度器(最新推荐)》ApacheAirflow调度器是数据管道管理系统的关键组件,负责编排dag中任务的执行,通过理解调度器的角色和工作方式,正确配置调度器,并... 目录什么是Airflow 调度器?Airflow 调度器工作机制配置Airflow调度器调优及优化建议最

微服务架构之使用RabbitMQ进行异步处理方式

《微服务架构之使用RabbitMQ进行异步处理方式》本文介绍了RabbitMQ的基本概念、异步调用处理逻辑、RabbitMQ的基本使用方法以及在SpringBoot项目中使用RabbitMQ解决高并发... 目录一.什么是RabbitMQ?二.异步调用处理逻辑:三.RabbitMQ的基本使用1.安装2.架构