异步编程需要“意识” 推荐 原创 边城狂人 2018-02-22 16:59:52 博主文章分类:软件开发 ©著作权 文章标签 异步 编程思想 文章分类 软件研发 ©著作权归作者所有:来自51CTO博客作者边城狂人的原创作品,请联系作者获取转载授权,否则将追究法律责任 虽然我们生活在一个异步的世界里,但对于多数编程初学者来说,异步还是很陌生。学习一门编程语言,通常都是从同步流程开始的,即顺序、分支和循环。而异步流程是什么呢——开始一个异步调用,然后……就没有然后了。异步程序跑哪去了? 异步程序会以某种异步的形式在运行着,比如多线程、异步IO等,直到处理完成。那如果需要处理结果怎么办?给一个程序入口,让它处理完当前过程之后,把处理结果送到这个入口,然后执行另一段程序——俗称回调。回调一般使用 callback 这个名称,不过有时候我更喜欢使用 next,因为它代表着下一个处理步骤。 同步和异步的概念 现在我们接触到了一些概念,比如同步和异步,它们是什么? 这两个概念并不来源于编程语言,而是来源于低层指令,甚至更低层的——电路。它们是基于时序的两个概念,其中,“步”是指步调,所以同步表示相同的步调,而异步表示不同的步调。当然这两个概念提升到程序这个级别的时候,精确的意思与时钟无关,但所表示的意义仍然未变。 同步 举个生活中的例子来说明这个问题——排除买票。售票厅开了一个窗口,有一队人在排队依次买票。这个队伍中,前面一个人往前走了一步,后面的人才能往前走一步;前面的人在等待,后面的人就一定在等待。那么在理想的情况下,所有人可以同时向前迈步。OK,大家步伐一致,称为同步。 这里把售票窗口看作是处理器,每个人看作是等待执行的指令,买票这个动作就是在执行指令。它的特点是按步就班,如果一个人买票时间过长(指令执行时间过长),就会造成阻塞。 异步(多线程) 现在买票的人渐渐多起来,所以售票厅多开了几个窗口同时售票。每个单独的队伍仍然保持着同步,但不同的队伍之间,步伐不再一致,称为异步。A 队列售票很顺利,队伍在有序快速的前进,但 B 队列的某个顾客似乎在付费时遇到点麻烦,花了很长的时候,造成阻塞,但这对 A 队列并不产生影响。 这时候的售票厅可以看作是在以多线程的方式运行着异步程序。从这个例子可以看到异步的两个特点:其一,两个异步流程之间相互独立,它们相互不会阻塞(有个前提,不需要等待共享资源的情况下);其二,异步程序内部仍然是同步的。 异步(IO) 上面的例子比较符合多线程异步的情况。那 IO 异步又是什么样呢? 年底了,M 在准备年终汇报的资料,这可是个紧张的工作(CPU),要收集不少数据来写好些文案。为了其中一份文案,M 需要车间的生产数据,但跑一趟车间(IO)可需要花不少时间,所以他让 N 去车间收集数据,自己则继续写其它方案,同时等 N 把数据收集回来(启动异步程序)。半天以后,N 带回了数据(插入事件消息),M 继续完成手上的文案(完成当前事件循环),之后使用 N 带回来的数据开始撰写关于车间的报告(新的事件循环)…… IO 的处理速度比 CPU 慢得多,所以 IO 异步让 CPU 不必闲置着等待 IO 操作完成。当 IO 操作完成之后,CPU 会适地使用 IO 操作结果继续工作。 同步逻辑和异步逻辑 回到程序上来,我们以一个函数的处理过程来描述同步和异步的处理方式。 同步逻辑 那么,同步处理过程是: 接受输入 ⇒ 处理 ⇒ 产生输出 用一段伪代码来描述就是 注:本文中的伪代码比较接近 Javascript 语法,而有时候为了说明类型,采用了 TypeScript 的类型申明语法。 function func(input) { do something with input return output } 这是标准的 IPO(Input-Process-Output) 处理。 异步逻辑 而异步呢,是: 接受输入 ⇒ 处理 ⇒ 启动下一步(如果有) 用伪代码来描述就是: function asyncFunc(input, next) { do something with input if (next is a entry) { next(output) } } 这个过程称为 IPN(Input-Process-Next)。 注意到这里的 Next,下一步,只有一步。这一步,囊括了后续的若干步骤。所以这一步,只能是后续若干步骤封装出来一个模块入口,或者说函数。 因此,模块化思想在异步思维中是一个非常关键的思想。很多初学者写代码喜欢像记流水账一样一句句往下写,动不动就是成百上千行的函数,这就是一种缺乏模块化思想的表现。模块化思想需要训练,分析代码的相关性,提炼函数,提取对象,在具有一定经验之后还需要掌握模块细化的粒度平衡。这不是一朝一夕之功,不过我推荐看看“设计模式”和“重构”相关的书籍。 异步开发工具(SDK和语法层面的) 承诺(Promise) 再想想上面关于年终汇报的例子,M 请 N 去车间收集数据的时候,N 会说:“好的,我很快就把数据带回来”,这是一种承诺。基于这个承诺,M 才能安排后面撰写关于车间的汇报材料。这个过程用伪代码来描述就是 function collectData(): Promise { // N 去收集数据,产生了一个承诺 return new Promise(resolve => { collect data from workshop // 这个承诺最终会带来数据 resolve(data) }) } function writeWorkshopReport(data) { write report with data } // 收集数据的承诺兑现之后,可将这个数据用于写报告 collectData() .then(data => writeWorkshopReport(data)) 以 Javascript 为代表的一些语言 SDK 中使用了 Promise。不过 C# 中是采用的 Task 和 Task<T>,相应的,使用了 Task.ContinueWith 和 Task<T>.ContinueWith 来代替 Promise.then。 异步逻辑同步化 上面提到了同步思维和异步思维在一个处理步骤中的区别。如果跳出一个处理步骤,从更大范围的处理流程来看,异步与同步其实也没多大区别,都是 输入-->处理-->产生输出-->将输出用于下一步骤,唯一要注意的是需要等待异步处理产生的输出,我们可以称之为异步等待。由于我们可以一边进行异步等待(async wait,简写 await),一边做别的事情,所以这个等待并不产生阻塞。但是,由于声明了这个等待,编译器/解释器会将后面的代码自动放在等待完成之后调用,这让异步代码写起来就像写同步代码一样。 上面的例子使用异步等待的伪代码会像这样 async function collectData(): Promise { collect data from workshop // 多数语言会把 async 函数的返回值封装成 Promise return data } function writeWorkshopReport(data) { write report with data } // await 只能用于声明为 async 的函数中 async function main() { data = await collectData() writeWorkshopReport(data) } // 定义了异步 main 函数,一定要记得调用,不然它是不会执行的 main() 像 C# 和 Javascript 等语言都从语法层面规定了 await 必须用在声明为 async 的函数中,这就从编译/解释的层面限定了 await 的用途,只要使用了 await,那它所处的就一定是一个异步上下文。而 async 也要求编译器/解释器对其返回值进行一些自动处理,比如在 Javascript 中,其返回值如果不是 Promise 对象,它会自动封装成一个 Promise 对象;而在 C# 中,它会自动封装成 Task 或 Task<T>(所以 async 方法的类型需要声明为 Task 或 Task<T>)。 注意,注意,注意 尽管语言服务在异步程序同步化方面已经做了很多工作,但是仍然避免不了一些人为错误,比如忘记写 await 关键字。在强类型语言中编译器会检查得严格一些,但如果是在 Javascript 中,忘记写 await 意味着原本应该取得一个值的语句,会取到一个 Promise。解释器不会对此质疑,但程序运行的结果会不正确。 小结 总的来说,异步编程并不是特别困难的事情。使用 async/await 语言特性甚至可以用类似编写同步代码的方法来编写异步代码。但语法糖终究是糖,要想把异步编程掌握得更好,还是需要去了解和熟悉异步、回调、Promise、模块化、设计模式、重构等概念。 相关阅读 从小小题目逐步走进 Javascript 异步调用 闲谈异步调用“扁平”化 理解 Javascript 的 async/await C# 并行计算(Parallel 和 ParallelQuery) 赞 收藏 评论 分享 举报 上一篇:Token 认证的来龙去脉 下一篇:使用递归遍历并转换树形数据(以 TypeScript 为例) 提问和评论都可以,用心的回复会被更多人看到 评论 发布评论 全部评论 () 最热 最新 相关文章 什么是异步编程? 异步编程在C#中通常使用async和await关键字来实现。这种模式允许方法异步地执行,这意味着方法可以在等待某些操作(如网络请求)完成时执行其他代码。async 关键字async关键字标记一个方法为异步方法,这意味着该方法可能会包含一个或多个await表达式。async方法通常会返回一个Task或Task<TResult>类型的对象,这代表了方法的异步执行。await 关键字awai 异步编程 网页内容 异步方法 C++ Boost 异步网络编程基础 Boost库为C++提供了强大的支持,尤其在多线程和网络编程方面。其中,Boost.Asio库是一个基于前摄器设计模式的库,用于实现高并发和网络相关的开发。Boost.Asio核心类是io_service,它相当于前摄模式下的Proactor角色。所有的IO操作都需要通过io_service来实现。在异步模式下,程序除了发起IO操作外,还需要定义一个用于回调的完成处理函数。io_service将 回调函数 构造函数 时间间隔 Boost 异步编程模型 JS中的异步编程与Promise 一、Javascript的异步编步机制在了解Javascript的异步机制之前,我们首先需要理解Javascript是一种单线程语言。单线程就意味着所有的任务需要按照顺序一次执行,如果前一个任务没有完成,后一个任务就无法开始。这个特性在执行大量或耗时任务时可能会导致阻塞或者界面卡死,这显然是不可取的。为了解决这个问题,Javascript引入了异步编程的机制。简单地说,异步就是你现在发出了一个“命 事件循环 任务队列 异步操作 程序员要有编程意识 2006-12-29 09:16 邹健 本文章取名《编程意识》,自然与“编程”和“意识”密不可分,而“编程意识”正是作者编程过程中积累下来的财富。我对那些并不是太懂编程的朋友们的一些个人建议,实属一家之言。但时我的方法的确是有效的,至少在我是这样。本文中要讲的内容:第二部分:讲述一些基本理论;第三部分:分析编程意识的形成过程。 AD: 这文章是我去年写的,正好病愈归来感悟良多,现在看来也是些 编程 语言 数据库 vb.net windows 异步编程 概念 异步编程核心为异步操作,该操作一旦启动将在一段时间内完成。所谓异步,关键是实现了两点:(1)正在执行的此操作,不会阻塞原来的线程(2)一旦启动的此操作,可以继续执行其他任务。当该操作完成时,将调用回调函数来通知该操作已经结束。【注】:本人一直以为同步和异步都属于多线程的范畴,到今天才明白完全错 异步方法 线程池 多线程 Java 详解异步编程 我们知道Javascript语言的执行环境是单线程,也就是一次只能完成一个任务。如果有多个任务就必须排队,前面一个任务完成,再执行后面的一个任务这种模式虽然实现起来简单,执行环境相对单纯,但是只要有一个任务耗时很长,后面的任务都必须排队等着,会拖延整个程序的执行。常见的有的浏览器无响应(假死,往往就是因为某一段JS代码长时间运行(比如死循环),导致整个页面卡在这个地方,其他任务无法执行。为了解... 异步编程 ajax 回调函数 异步操作 c函数 JS异步编程 JS异步编程并发(concurrency)和并行(parallelism)区别并发是宏观概念,我分别有任务 A 和任务 B,在一段时间内通过任务间的切换 js 回调函数 异步编程 嵌套 python 异步编程 python 必备技能协程和asyncio await使用教程 异步编程 asyncio await 协程 asyncio异步编程 1. 协程 协程不是计算机提供,程序员认为创造 协程(Coroutine),也可以被称为微线程,是一种用户态内的上下文切换技术,其实就是一个线程实现代码块相互切换执行。例如: def func1(): print(1) ... print(2) def func2(): print(3) ... asyncio 协程 python之路 异步IO编程 import asyncioimport threading#异步IO编程:# asyncio 提供了完善的异步 IO 支持;# 异步操作需要在 coroutine 中通过 yield from 完成;# 多个 coroutine 可以封装成一组 Task 然后并发执行。@asyncio.coroutinedef hello(): print('hello world threadId:%s 异步操作 异步io 封装 WinSock异步编程 s的消息是异步的,不按照事先定义的顺序发生的。 当程序开始一个任务时,可以告诉Windows在任务完成时发送 后端 数据 应用程序 客户端 CompletableFuture异步编程 CompletableFuture 有什么用CompletableFuture是用来描述多线程任务的时序关系的:串行关系, 线程池 System ide .NET中的异步编程-为什么需要异步 1.什么是async/await? await和async是.NET Framework4.5框架、C#5.0语法里面出现的技术,目的是用于简化异步编程模型。 2.async和await的关系? async和await是成对出现的。async出现在方法的声明里,用于批注一个异步方法。光有async是 ... 异步编程 .net web应用 服务器 异步请求 Java 异步编程 java异步编程视频 一、启动一个异步任务runAsync 简单开启一个独立的线程,异步完成一个任务:runAsync不会返回结果 Java 异步编程 System 前端开发 前台页面 python异步编程 python异步网络编程 Python的网络编程(三)非阻塞或异步编程例如,对于一个聊天室来说,因为有多个连接需要同时被处理,所以很显然,阻塞或同步的方法是不合适的,这就像买票只开了一个窗口,佷多人排队等一样。那么我们如何解决这个问题呢?主要有三种方法:forking、threading、异步I/O。Forking和threading的方法非常简单,通过使用SocketServer服务类的min-in类就可以实现。fork python异步编程 服务器 客户端 事件处理 异步编程架构 异步编程的好处 我们之所以要花大力气学习APM,就必须要清楚它能解决实际编程中的那些难题。以及现有的技术为什么不行。简单点说:APM是基于IAsyncResult接口的,采用的BeginXXX和EndXXX的形式来实现异步。下面这几点就是APM的优势:1,线程执行是异步的,不会阻塞调用线程。这一点也是我们使用异步的主要目的,我们不就是希望后台处理一些耗时操作吗?2,任务完成可以得到通知。(非阻塞)3,任务可以实现 异步编程架构 线程 异步 System FileStream python的异步编程 python 异步编程 本文是写给 Javascript 程序员的 Python 教程。Python 的异步编程,其他人可能觉得很难,但是 Javascript 程序员应该特别容易理解,因为两者的概念和语法类似。Javascript 的异步模型更简单直观,很适合作为学习 Python 异步的基础。本文解释 Python 的异步模块 asyncio 的概念和基本用法,并且演示如何通过 Python 脚本操作无头浏览器 py python的异步编程 Python 异步任务 python 异步编程架构有哪些 异步编程框架 DActorIntroductionDActor框架可同时支持同步和异步代码,简化在线异步代码的开发,用同步代码的思维来开发异步代码,兼顾异步代码的高并发、无阻塞和同步代码的易读性,可维护性。 基于协程思想设计 最大程度的降低阻塞,提高单个线程的处理能力,并可有效的降低线程数。Overview目前开发过程中的几个常见模型 – 同步编程 所有步骤都在一个主线程中完成,调用一个方法,等待其响应返回。 异步编程架构有哪些 python异步编程框架 json github 异步编程 python异步编程库 python generator异步编程 Python的语法是简洁的,也是难理解的。比如yield关键字: def fun(): for i in range(5): print('test') x = yield i print('good', x)if __name__ == '__main__': a = fun() # print(a.__next__ python异步编程库 python 操作系统 epoll 生成器 future java异步编程 java异步编程框架 1 Executor框架的简介 1.5后引入的Executor框架的最大优点是把任务的提交和执行解耦。要执行任务的人只需把Task描述清楚,然后提交即可。这个Task是怎么被执行的,被谁执行的,什么时候执行的,提交的人就不用关心了。具体点讲,提交一个Callable对象给ExecutorService(如最常用的线程池ThreadPoolExec future java异步编程 java 线程池 主线程 返回结果