互联网我来了 -- 2. js中"异步/阻塞"等概念的简析

一、什么是”异步非阻塞式”?

这个名字听起来很恶心难懂,但如果以 买内裤 这件事情来比喻执行程序的话就很容易理解“异步非阻塞式”的涵义了。

例如你是一个CPU的线程,你需要去执行一段 买内裤的程序, 你所需执行的步骤大致如下,

  1. 到一个商店里问老板, 你们店里还有没有nb牌内裤?
  2. 买到内裤,穿上
  3. 去小卖店买点火腿回家喂狗

这时候,你作为一个线程,你可能会遇到几种状况或选择。

  1. 店里面没货了,老板一直不答应你(阻塞你),你也一直等着(同步),第三天有货了才告诉你有了,你赶紧拿到穿上,再去买火腿 – [同步阻塞模式]
  2. 老板马上告诉你“没货了”(不阻塞你),然后你每天去店里问一声,直到有货了赶紧穿上,再去买东西喂狗 – [同步非阻塞]
  3. 你让老板有货了打电话叫你过来取,老板说“好的”(非阻塞),然后你就先去买东西喂狗了,过了两天老板叫你过去,你才拿到内裤并穿上 – [异步非阻塞]
  4. 你让老板有货了打电话叫你过来取, 老板又没答应你(阻塞), 然后你本来打算去先去买火腿的(异步),这时候也没法去了。 – [异步阻塞]

很明显,第三种方法是最聪明,前两种方法都略显效率低下。所以根据我们的理解,

同步或非同步,表明着是否需要将整个流程顺序地完成

阻塞或非阻塞,意味着你调用的函数会不会立刻告诉你结果

二、在js中的阻塞与同异步

你有一个函数和一段程序。

2.1 js中的同步阻塞

// 这是一个阻塞式函数, 将一个文件复制到另一个文件上
function copyBigFile(afile, bfile){
    var result = copyFileSync(afile,bfile);
    return result;
}

调用这个”copyBigFile()”函数,将一个大文件复制到另一个文件上,将耗时1小时。意味着这个函数的将在一个小时之后返回。

//这是一段程序
console.log("start copying ... ");
var a = copyBigFile(‘A.txt‘, ‘B.txt‘);  //这行程序将耗时1小时
console.log("Finished");   // 这行程序将在一小时后执行
console.log("处理一下别的事情");  // 这行程序将在一小时后执行
console.log("Hello World, 整个程序已加载完毕,请享用"); // 这行程序将在一小时后执行

以上的程序就是一个同步阻塞的例子,因为copyFileSync函数返回值的过程需要漫长的时间,所以线程也无法继续执行下去,只能等待。

2.2 js中的同步非阻塞

// 这是一个非阻塞式函数
// 如果复制已完成,则返回 true, 如果未完成则返回 false
function copyBigFile(afile,bfile){
    var copying = copyFileAsync(afile, bfile);
    var isFinished = !copying;
    return !isFinished;
}

调用这个函数将立刻返回结果,然后你的程序就可以写成

console.log("start copying ... ");
while( a = copyBigFile(‘A.txt‘, ‘B.txt‘)){
  console.log("在这之间还可以处理别的事情");
} ;
console.log("Finished");   // 这行程序将在一小时后执行
console.log("Hello World, 整个程序已加载完毕,请享用"); // 这行程序将在一小时后执行

一个非阻塞式的函数,给你的编程带来了更多的便利,你可以在长IO操作的同时,写点其他的程序,提高效率。执行结果如下

start copying ...
在这之间还可以处理别的事情
在这之间还可以处理别的事情
在这之间还可以处理别的事情
...
Finished
Hello World, 整个程序已加载完毕,请享用

2.3 js中的异步非阻塞

我们看到,一个非阻塞式的函数能给我们编程带来许多灵活性,我们喜欢非阻塞式的函数。

但是,又可以看到同步的程序需要在一个循环中轮询结果,循环里面的程序会被执行好多遍,所以并不好控制来写一些正常的程序,很难再利用起来。

所以我们需要一种更为合理的方式对非阻塞式的函数进行利用。

也就是我不会主动地去询问结果,而是当你有了结果的时候再来通知我。

// 这是一个非阻塞式函数

// 如果复制已完成,则返回 true, 如果未完成则返回 false

//非阻塞式的有异步通知能力的函数
//以下不需要看懂,只用知道这个函数会在完成copy操作之后,执行success
function copyBigFile(afile,bfile, callback){
    var copying = copyFileAsync(afile, bfile, function(){ callback();});
    var isFinished = !copying;
    return !isFinished;
}

这个函数不同于上一个同步非阻塞函数的地方在于,它具有通知功能,也就是说,它能够在完成操作之后主动地通知程序,“我完成了”。于是有程序如下,

console.log("start copying ... ");
copyBigFile("A.txt","B.txt", function(){
          console.log("Finished");   //一个小时后被执行
          console.log("Hello World, 整个程序已加载完毕,请享用"); //一个小时后被执行
          })
console.log("干别的事情");
console.log("做一些别的处理");

程序在调用copyBigFile函数之后,可以立即获得返回值,线程没有被阻塞住,于是还可以去干些别的事情,然后当copyBigFile完成之后,会执行指定的函数。所以程序的输出应为,

start copying ...
干别的事情
做一些别的处理
Finished
Hello World, 整个程序已加载完毕,请享用

在这种情况下,程序更容易控制,流程更为清晰。一些“别的事情”可以在函数还未通知之前进行处理,充分地提高了线程的利用效率。

三、提升

在以上的程序中,我们的程序需要拷贝一个巨大的文件。其实拷贝文件这个过程是留给系统的IO调用进行完成的,而我们的线程并不需要去处理拷贝的细节。

所以通过非阻塞式的函数,我们能够 有可能 利用线程资源去干一下别的事情。

而通过异步调用方式,能使得程序流程 更容易控制,更有效率地利用线程资源。

而js是通过传递函数实现异步的。(还有可以通过promise的方式来实现异步…)

时间: 2024-10-13 13:54:36

互联网我来了 -- 2. js中"异步/阻塞"等概念的简析的相关文章

WebGL 中 OpenGL ES 指令与 iOS 中 C 版指令的差异简析

太阳火神的美丽人生 (http://blog.csdn.net/opengl_es) 本文遵循"署名-非商业用途-保持一致"创作公用协议 转载请保留此句:太阳火神的美丽人生 -  本博客专注于 敏捷开发及移动和物联设备研究:iOS.Android.Html5.Arduino.pcDuino,否则,出自本博客的文章拒绝转载或再转载,谢谢合作. WebGL 中 OpenGL ES 指令与 iOS 中 C 版指令的差异,从整体上看,应该是 gl 前缀在 WebGL 版指令中的省略,举例对比如

Web worker 与JS中异步编程的对比

0.从一道题说起 var t = true; setTimeout(function(){ t = false; }, 1000); while(t){ } alert('end'); 问,以上代码何时alert"end"呢? 测试一下:答案是:永远都不会alert. 解析:JavaScript引擎是单线程的,事件触发排队等候.所有任务按照触发时间先后排队处理. 上例中,排队的顺序状态是: | var t=true ; | while(t){}; | alert('end'); | 在

JS中异步和单线程

JS 在客户端运行的时候,只有一个线程可运行,因此想要两件事儿同时干是不可能的.如果没有异步,我们只能同步干,等待过程中卡住了,但是有了异步就没有问题了.那么单线程是如何实现异步的呢? console.log(100) setTimeout(function () { console.log(200) }) console.log(300) 那上面的示例来说,有以下几点.重点从这个过程中体会单线程这个概念,即事情都是一步一步做的,不能两件事儿一起做. 执行第一行,打印100 执行setTimeo

JS中容易混淆的概念。

1.attribute和porperty的区别 attribute是特性节点.每个DOM元素都有一个对应的attributes属性来存放所有的attribute节点,attributes是一个类数组的容器,说得准确点就是NameNodeMap,总之就是一个类似数组但又和数组不太一样的容器.attributes的每个数字索引以名值对(name=”value”)的形式存放了一个attribute节点. 要设置一个attribute节点使用setAttribute方法,要删除就用removeAttri

js中异步和同步

js引擎 js引擎是浏览器的重要组成部分,重要用于读取js和执行js代码. js引擎执行js时是单线程执行的. js执行为什么是单线程? 试想一下:如果js是多线程执行的,假设现在有两个线程p1,p1,那么这两个线程可以同时对同一个dom元素进行操作 比喻说,p1对dom元素进行更新操作,p2对dom元素进行删除操作,这样就会引起混乱. 既然是单线程执行,就说明js代码是从上往下一行一行解析执行的,只有上一行代码执行完毕了才会执行下一行代码.如果上一行代码解析时间很长,那么下一行代码就会被阻塞,

Linux中 /proc/[pid] 目录各文件简析

Linux 内核提供了一种通过 proc 文件系统,在运行时访问内核内部数据结构.改变内核设置的机制.proc 文件系统是一个伪文件系统,它只存在内存当中,而不占用外存空间.它以文件系统的方式为访问系统内核数据的操作提供接口. 用户和应用程序可以通过 proc 得到系统的信息,并可以改变内核的某些参数.由于系统的信息,如进程,是动态改变的,所以用户或应用程序读取 proc 文件时,proc 文件系统是动态从系统内核读出所需信息并提交的. 下面列出的这些文件或子文件夹,并不是都是在你的系统中存在,

转:MYSQL中的乐观锁实现(MVCC)简析

from: https://segmentfault.com/a/1190000009374567 什么是MVCC MVCC即Multi-Version Concurrency Control,中文翻译过来叫多版本并发控制. MVCC是解决了什么问题 众所周知,在MYSQL中,MyISAM使用的是表锁,InnoDB使用的是行锁.而InnoDB的事务分为四个隔离级别,其中默认的隔离级别REPEATABLE READ需要两个不同的事务相互之间不能影响,而且还能支持并发,这点悲观锁是达不到的,所以RE

【译】深入理解python3.4中Asyncio库与Node.js的异步IO机制

转载自http://xidui.github.io/2015/10/29/%E6%B7%B1%E5%85%A5%E7%90%86%E8%A7%A3python3-4-Asyncio%E5%BA%93%E4%B8%8ENode-js%E7%9A%84%E5%BC%82%E6%AD%A5IO%E6%9C%BA%E5%88%B6/ 译者:xidui原文: http://sahandsaba.com/understanding-asyncio-node-js-python-3-4.html 译者前言 如

promise 的基本概念 和如何解决js中的异步编程问题 对 promis 的 then all ctch 的分析 和 await async 的理解

* promise承诺 * 解决js中异步编程的问题 * * 异步-同步 * 阻塞-无阻塞 * * 同步和异步的区别? 异步;同步 指的是被请求者 解析:被请求者(该事情的处理者)在处理完事情的时候的通知机制. 异步:当事情处理完成后被请求者会发信息通知请求者该事情处理完成.在这期间被请求者可以选择是继续等待命令请求完成还是去做其他事等待被请求者返回. 同步:当事情处理完成后被请求者不会告知请求者,等到请求者发来询问是才会告知 阻塞:非阻塞 指的是请求者 阻塞:针对请求者来说的,委托其他人处理一