同步异步,回调

聊聊同步、异步和回调

给产品经理讲技术 ? 2016-01-04 ? 深氪

有一天,你找到公司刚来的程序员小T,跟他说:我们要加个需求,你放下手里的事情优先支持,我会一直等你做完再离开。小T微笑着答应了,眼角却滑过一丝不易觉察的杀意。

本文来自微信公众号“给产品经理讲技术”(pm_teacher),欢迎大家关注。

有一天,你找到公司刚来的程序员小T,跟他说:“我们要加个需求,你放下手里的事情优先支持,我会一直等你做完再离开”。小T微笑着答应了,眼角却滑过一丝不易觉察的杀意。

切入正题。世界上的所有事情大致可以分为同步去做和异步去做两种。你打电话去订酒店,电话另一边的工作人员需要查下他们的管理系统才能告诉你有没有房间。这时候你有两种选择,一种是不挂电话一直等待,直到工作人员查到为止(可能几分钟也可能几个小时,取决于他们的办事效率),这就是同步的。另一种是工作人员问了你的联系方式就挂断了电话,等他们查到之后再通知你,这就是异步的,这时候你就可以干点其他事情,比如把机票也定了之类的。同步和异步的区别就在于,在下达了执行任务的命令后,是等到执行完成之后才能得到结果呢,还是马上就知道了结果(尽管是不确定的答案)。

计算机世界也是如此。我们写的代码是交给CPU去执行的,在这个过程中经常面临是让CPU同步执行还是异步执行的选择。比如我写了一个APP,它可以帮你下载网络上的一个文件。当你输入一个文件的网址,按下下载按钮的一瞬间,CPU就收到了一个下载文件的任务。我们先想象一下同步执行时什么情况。CPU立刻停掉了手头的事情,包括绘制界面、对用户的点击做出响应等等,倾尽全力去帮你下载文件。但是,这时候你会发现,你的屏幕再也没有响应了,整个系统就像死了一样(废话,CPU都被你的下载任务抢走了)。过几秒钟,如果是Android系统则会弹出一个下面图1的提示,用户非常感动,然后无情的卸载了这个APP(尼玛裤子都脱了,你让我看这个)。同样的情况异步执行要好很多。CPU马上告诉你任务已经被受理了,等下载完成我会通知你的。于是呢,屏幕照样刷新,用户点击都能做出处理,就好像没有下载过一样。然而CPU并没有闲着,它开启了一个线程,专门处理这个下载任务(还记得之前讲过的线程的概念吗?不用担心我们下面会详细讲)。过了几个小时下载完了,你会收到一个通知,告诉你任务执行的结果(图2)。

一般情况下计算机通过多线程来实现同步,你可以把线程看做是富土康生产iPhone的一条生产线。它给生产一台完整的iPhone提供了所有必须的资源:包括人力,原料,设计图纸等等。生产任务来的时候,如果是同步的,那一条生产线就够了,所有的小伙伴们蜂拥而上,不一会儿就搞定了。如果是异步的,那就必须新建一条生产线(好在CPU创建线程的成本并不高),分一部分资源到新的生产线上,这样可以同时生产两台手机。那么生产线可以无限制增加吗?答案是不行的。一是异步会面临资源竞争的问题。比如说8条生产线都要组装电池,但是电池原料只有4份,那么必然会存在其他4条生产线等待的其情况,如果资源竞争比较频繁,甚至异步的执行效率要低于同步。二是异步会导致状态难以管理。比如车间主任想要统计一共生产了多少iPhone,就必须要询问完所有生产线才能得出结论,而且这个询问过程必须要停掉所有的生产线,同步来做。

讲到这里,回调的概念呼之欲出。上面异步任务的整个过程是首先你要把自己的信息给异步任务执行者,等执行完成的时候,执行者可以通过这些信息找到你,并给你一个通知。把自己信息给别人的过程叫做注册,别人找到你给你通知的过程就叫做回调。上面的例子,你把自己的联系方式给了酒店工作人员叫做注册,工作人员完成任务后联系你叫做回调。但是回调的概念其实非常广,这里可以抽象成先把要做的事情注册给别人,等条件满足的时候别人再回过头来调用你的模型。程序上响应一个按钮点击之后要做的事情也是用回调来做的。程序员先把用户点了按钮要做的事情先写好(比如要下载文件),注册给系统。等用户点击到按钮的时候,系统就会回调你下载文件的代码。

回到开篇,了解了同步、异步以及回调之后,你会这样跟小T说:”我们要加个需求,你抽时间支持下,等你做完了记得通知我。“小T欣然理接受,眼角闪过理解万岁的泪光,回头就把这事儿忘了。

时间: 2024-11-11 16:48:18

同步异步,回调的相关文章

js同步-异步-回调

出处:https://blog.csdn.net/u010297791/article/details/71158212(1)上面主要讲了同步和回调执行顺序的问题,接着我就举一个包含同步.异步.回调的例子. let a = new Promise(//声明了一个Promise回调函数,能够使用then function(resolve, reject) { console.log(1) setTimeout(() => console.log(2), 0) console.log(3) cons

同步异步 + 回调函数

重点记忆 异步回调函数 如果进程池+回调: 回调函数由主进程去执行. 如果线程池+回调: 回到函数由空闲的线程去执行.(比如有4个线程,10个任务,第一轮完成4个任务,交由主线程处理结果,第二轮同样如此,但是第三轮将会空闲出2个子进程,则这2个子进程将会和主进程一同处理结果,以此类推,当所有的任务完成时,所有的子进程和主进程一起处理结果,增加效率) 回调函数不管有没有返回数据,返回值都是None,回调函数内部加函数名是调用此函数,obj隐形传参 1.概念 1. 从执行的角度 阻塞: 程序运行时,

协程,事件,队列,同步,异步,回调函数

协程 什么是协成?单个线程并发的处理多个任务,程序控制协成的切换+保持状态,协成的切换速度非常快,蒙蔽了操作系统的眼睛,让操作系统认为CPU一直在运行 进程或线程都是由操作系统控制CPU来回切换,遇到阻塞就切换执行其他任务,协成是程序控制的,霸占CPU执行任务,会在操作系统控制CPU之前来回切换,操作系统就认为CPU一直在运作 协程的优点: 1.开销小 2.运行速度快 3.协程会长期霸占CPU只执行我程序里的所有任务 协程的缺点: 1.协程属于微并发,处理任务不易过多 2.协程的本质是单线程,无

python 管道 事件 信号量 进程池(map/同步/异步)回调函数

####################总结######################## 管道:是进程间通信的第二种方式,但是不推荐使用,因为管道会导致数据不安全的情况出现 事件:当我运行主进程的时候 需要子执行某个进程后 需要的返回值时 可以使用 信号量:互斥锁同时只允许一个线程更改数据,而信号量Semaphore是同时允许一定数量的线程更改数据 . 内部维护了一个计数器,acquire-1,release+1,为0的时候,其他的进程都要在acquire之前等待 进程池:  进程的创建和销

同步、异步、异步回调

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using System.Runtime.Remoting.Messaging; namespace Async { public delegate int AddHandler(int a, int b); public class AddCls { public static

关于C10K、异步回调、协程、同步阻塞

最近到处在争论这些话题,发现很多人对一些基础的常识并不了解,在此发表一文做一下解释.此文未必能解答所有问题,各位能有一个大致的了解就好. C10K的由来 大家都知道互联网的基础就是网络通信,早期的互联网可以说是一个小群体的集合.互联网还不够普及,用户也不多.一台服务器同时在线100个用户估计 在当时已经算是大型应用了.所以并不存在什么C10K的难题.互联网的爆发期应该是在www网站,浏览器,雅虎出现后.最早的互联网称之为Web1.0, 互联网大部分的使用场景是下载一个Html页面,用户在浏览器中

C# 委托的三种调用示例(同步调用 异步调用 异步回调)

本文将主要通过同步调用.异步调用.异步回调三个示例来讲解在用委托执行同一个加法类的时候的的区别和利弊 首先,通过代码定义一个委托和下面三个示例将要调用的方法: public delegate int AddHandler(int a,int b); public class 加法类 { public static int Add(int a, int b) { Console.WriteLine("开始计算:" + a + "+" + b); Thread.Slee

C#委托调用(同步调用,异步调用,异步回调)

#region 委托回调 static void delegateTest() { Console.WriteLine("同步调用"); SubDelegate subDel = Sub; var result = subDel.Invoke(3, 4); Console.WriteLine("继续"); Console.WriteLine(result); Console.ReadKey(); Console.WriteLine("异步调用")

2015/01/23 – 不要对异步回调函数进行同步调用

绝对不能对异步回调函数(即使在数据已经就绪)进行同步调用. 如果对异步回调函数进行同步调用的话,处理顺序可能会与预期不符,可能带来意料之外的后果. 对异步回调函数进行同步调用,还可能导致栈溢出或异常处理错乱等问题. 如果想在将来某时刻调用异步回调函数的话,可以使用 setTimeout 等异步API. function onReady(fn) { var readyState = document.readyState; if (readyState == 'interactive' || re