Node.js学习笔记(二):非阻塞异步IO模式

何为非阻塞异步IO模式?

观察下面的实例,调用readFile()方法,读取‘HelloNode.js’中的文件内容,读取结束后,打印到屏幕,接下来退出readFile()方法,执行"console.log('Conde End:在同步编程下,这一句最后执行')"。按照线性编程思想,程序本该一句接着一句执行,但是在Node.js中,输出结果却是先执行最后的输出,然后才打印文件信息。

var fs=require('fs');
fs.readFile('HelloNode.js','UTF-8',function(err,data){
  if(err){
  console.log(err);
 }else
  console.log(data);
});
console.log('Code End:在同步编程下,这一句最后执行');//在同步编程下,这一句最后执行

为什么会出现以上的情况,这里必须结合异步式IO模式的机制来理解。

何为阻塞:

      什么是阻塞(block)呢?线程在执行中如果遇到磁盘读写或网络通信(统称为 I/O 操作), 通常要耗费较长的时间,这时操作系统会剥夺这个线程的 CPU 控制权,使其暂停执行,同时将资源让给其他的工作线程,这种线程调度方式称为——阻塞。当 I/O 操作完毕时,操作系统将这个线程的阻塞状态解除,恢复其对CPU的控制权,令其继续执行。这种 I/O 模式就是通 常的同步式 I/O(Synchronous I/O)或阻塞式 I/O (Blocking I/O)。

      相应地,异步式 I/O (Asynchronous I/O)或非阻塞式 I/O (Non-blocking I/O)则针对 所有 I/O 操作不采用阻塞的策略。当线程遇到 I/O 操作时,不会以阻塞的方式等待 I/O 操作 的完成或数据的返回,而只是将 I/O 请求发送给操作系统,继续执行下一条语句。当操作 系统完成 I/O 操作时,以事件的形式通知执行 I/O 操作的线程,线程会在特定时候处理这个 事件。为了处理异步 I/O,线程必须有事件循环,不断地检查有没有未处理的事件,依次予 以处理。

      结合上面的例子,线程执行到fs.readFile()方法时,由于线程进入到读取文件的事件中,线程不会以阻塞的方式等待I/O操作,继续执行"console.log('Code End...')",执行完成后进入事件循环监听事件,当fs接收到IO请求完成的事件时,即等文件读取完毕后,事件循环会主动调用回调函数,来打印文件信息。这就是为什么会出现先执行后面的语句的原因。异步式IO的最直观表现就是避免了线程等待IO事件。

阅读更多
想对作者说点什么?

博主推荐

换一批

没有更多推荐了,返回首页