Node.js (2) — 异步式I/O与事件式编程

 

目录

一、阻塞与线程

二、回调函数

三、事件


         Node.js最大的特点就是异步式I/O(或者非阻塞I/O)与事件紧密结合的编程模式。这种模式与传统的同步式I/O线性的编程思路有很大的不同,因为控制流很大程度上要靠事件和回调函数来组织,一个逻辑要拆分成若干个单元

 

一、阻塞与线程

Q:什么是阻塞?

A: 线程在执行中如果遇到磁盘读写或网络通信(统称为I/O操作),通常要耗费较长的时间,这时操作系统会剥夺这个线程的CPU控制权,使其暂停执行,同时将资源让给其他的工作线程,这种线程调度方式称为阻塞。

 

同步式I/O(阻塞式I/O):当I/O操作完毕时,操作系统将这个线程的阻塞状态解除,恢复其对CPU的控制权,令其继续执行。这种I/O模式就是通常的同步式I/O(Synchronous I/O)或阻塞式I/O(Blocking I/O)。

异步式I/O(非阻塞式I/O):当线程遇到I/O操作时,将I/O请求发送给操作系统,继续执行下一条语句。当操作系统完成I/O操作时,以事件的形式通知执行I/O操作的线程,线程会在特定时候处理这个事件。为了处理异步I/O,线程必须有事件循环,不断地检查有没有未处理的事件,依次予以处理。

 

假设我们有一项工作,可以分为两个计算部分和一个I/O部分,I/O部分占的时间比计算多得多(通常都是这样)。如果我们使用阻塞I/O,那么要想获得高并发就必须开启多个线程。而使用异步式I/O时,单线程即可胜任。图示如下(多线程同步式I/O与单线程异步式I/O):

 

 

 

 

同步式I/O和异步式I/O的特点
同步式I/O(阻塞式) 异步式I/O(非阻塞式)
利用多线程提供吞吐量 单线程即可实现高吞吐量
通过事件片分割和线程调度利用多核CPU 通过功能划分利用多核CPU
需要由操作系统调度多线程使用多核CPU 可以将单进程绑定到单核CPU
难以充分利用CPU资源 可以充分利用CPU资源
内存轨迹大,数据局部性弱 内存轨迹小,数据局部性强
符合线性的编程思维 不符合传统编程思维

Q:单线程事件驱动的异步式I/O比传统的多线程阻塞式I/O好在哪里呢?

A:异步式I/O少了多线程的开销。对操作系统来说,创建一个线程的代价是十分昂贵的,需要给它分配内存、列入调度,同时在线程切换的时候还要执行内存换页,CPU的缓存被清空,切换回来的时候还要重新从内存中读取信息,破坏了数据的局部性。

 

二、回调函数

        在Node.js中用异步的方式读一个文件

var fs = require('fs')
fs.readFile('file.txt','utf-8',function(err, data) {
    if(err) {
        console.error(err)
    }else{
        console.log(data)
    }
})
console.log('end')

运行的结果如下:

 

 

另,Node.js也提供了同步读文件的API,操作如下:

var fs = require('fs')
var data = fs.readFileSync('file.txt','utf-8')
console.log(data)
console.log('end')

运行的结果如下:

  

        同步式读取文件是将文件名作为参数传入fs.readFileSync函数,阻塞等待读取完成后,将文件的内容作为函数的返回值赋给data变量,接下来控制台输出data的值,最后输出end。

        异步式I/O通过回调函数来实现,end先被输出。fs.readFile接收了三个参数,第一个是文件名,第二个是编码方式,第三个是一个函数,将这个函数称为回调函数。 fs.readfile调用时所做的工作只是将异步式I/O请求发送给了操作系统,然后立即返回并执行后面的语句,执行完以后进入事件循环监听事件。当fs接收到I/O请求完成的事件时,事件循环会主动调用回调函数以完成后续工作。因此我们会先看到end.,再看到file.txt文件的内容。

 

三、事件

        Node.js所有的异步I/O操作在完成时都会发送一个事件到事件队列。

Q:Node.js在什么时候会进入事件循环呢?

A:Node.js程序由事件循环开始,到事件循环结束,所有的逻辑都是事件的回调函数,所以Node.js始终在事件循环中,程序入口就是事件循环第一个事件的回调函数。事件的回调函数在执行的过程中,可能会发出I/O请求或直接发射(emit)事件,执行完毕后再返回事件循环,事件循环会检查事件队列中有没有未处理的事件,直到程序结束。如图所示:

 

Supongo que te gusta

Origin blog.csdn.net/m0_59897687/article/details/120977028
Recomendado
Clasificación