js与Nodejs的单线程和异步--初探

摘要:
来自同一任务源的所有任务必须放在同一任务队列中。1) Javascript引擎基于事件驱动的单线程执行。然而,由于JS的单线程关系,所有这些事件都必须排队等待JS引擎处理。node.js的事件模型:node.js不使用多个线程为每个请求执行工作。相反,它将所有工作添加到事件队列中,然后有一个单独的线程来提取队列中的事件。执行Node.js事件队列中的所有事件后,Node.js应用程序终止。Nodejs架构Nodejs具有异步机制和事件驱动。

Event Loop

  • Event Loop : 浏览器使用 Event Loop 来协调 DOM 事件、UI 渲染、脚本执行和网络事件等。
  • Task Queue (Event Queue) :每当 DOM 事件、计时器事件或者网络事件被触发时,它们的回调函数和 Context 都会被压入 Event Queue,而 Event Loop 则会从中取出回调函数并执行。

虽然JavaScript是单线程的(按顺序执行的主线程),但维护事件队列的是另一个线程(Event Loop)。每当某个事件被触发,它的回调函数就会等待在这个队列(Event Queue)里。

异步方法最主要有2点,一个是不阻塞当前代码的执行,另一个是有回调方法。即异步方法运行完可以通知主线程。

js与Nodejs的单线程和异步--初探第1张

Event Loop有browsing contexts和 workers两种类型。一个event loop可以有一个或多个task queues来自同一个task source的所有tasks必须放入同一个task queue。

通常有4种task source:DOM manipulation task source,user interaction task source,networking task source和history traversal task source。

同一个task queue是按先进先出顺序执行的。浏览器可以根据task queue中task source的不同,给予task queue不同的优先级。即由浏览器决定挑哪一个task queue中的队首task执行。

 

     浏览器的三个常驻线程

浏览器是多线程的,它们在内核制控下相互配合以保持同步。一个浏览器至少实现三个常驻线程:JavaScript引擎线程,GUI渲染线程,浏览器事件触发线程(UI线程)。

1) javascript引擎是基于事件驱动单线程执行的。JS引擎一直等待着event loop中任务的到来,然后加以处理(只有当前函数执行栈执行完毕,才会去任务队列中取任务执行)。浏览器无论什么时候都只有一个JS线程在运行JS程序。

2) UI渲染线程负责渲染浏览器界面,当界面需要重绘(Repaint)或由于某种操作引发回流(reflow)时,该线程就会执行。但是 GUI渲染线程与JS引擎是互斥的,当JS引擎执行时GUI线程会被挂起,JS对页面的操作即GUI的更新也会被保存在一个队列中,等到JS引擎空闲时才有机会被执行。这就是JS阻塞页面加载。

3) 事件触发线程,当一个事件被触发时该线程会把事件添加到任务队列的队尾,等待JS引擎的处理。这些事件可以来自JavaScript引擎当前执行的代码块调用setTimeout/ajax添加一个任务,也可以来自浏览器其他线程如鼠标点击添加的任务。但由于JS的单线程关系,所有这些事件都得排队等待JS引擎处理。

javascript要等主线程空了才会去查看子线程有没有回调内容。异步的任务执行的顺序是不固定的,主要看返回的速度。

function f() {
  console.log("foo");
  setTimeout(g, 0);
  console.log("baz");
  h();
}

function g() {
  console.log("bar");
}

function h() {
  console.log("blix");
}

f();
输出的结果为:foo 、baz 、 blix 、bar

 

浏览器的多线程技术

Web Worker(可开启独立运行在浏览器后台的js环境)

 

Nodejs的异步任务执行流程

js与Nodejs的单线程和异步--初探第2张

用户写的代码是单线程的,但nodejs内部并不是单线程!

node.js的事件模型

Node.js不是用多个线程为每个请求执行工作的,相反而是它把所有工作添加到一个事件队列中,然后有一个单独线程,来循环提取队列中的事件。事件循环线程抓取事件队列中最上面的条目,执行它,然后抓取下一个条目。当执行长期运行或有阻塞I/O的代码时,注意这里:它不会被阻塞,会继续提取下一个事件,而对于被阻塞的事件Node.js会从线程池中取出一个线程来运行这个被阻塞的代码,同时把当前事件本身和它的回调事件一同添加到事件队列(callback嵌套callback)。

当Node.js事件队列中的所有事件都被执行完成时,Node.js应用程序终止。

 

Nodejs架构

js与Nodejs的单线程和异步--初探第3张

        NodeJS的显著特点:异步机制、事件驱动。

点餐的厨房的例子:整个过程没有阻塞新用户的连接,也不需要维护连接。

基于这样的机制,理论上陆续有用户请求连接,NodeJS都可以进行响应,因此NodeJS能支持比Java、php程序更高的并发量。

虽然维护事件队列也需要成本,再由于NodeJS是单线程,事件队列越长,得到响应的时间就越长,并发量上去还是会力不从心。

RESTful API是NodeJS最理想的应用场景,可以处理数万条连接,本身没有太多的逻辑,只需要请求API,组织数据进行返回即可。

 

免责声明:文章转载自《js与Nodejs的单线程和异步--初探》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇sql 中延迟执行【原创】Capture CIS利用Access数据库建立封装库说明下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

android Launcher——启动过程详解

一LauncherApplication->onCreate        --1.//设置最小堆内存4M        --2.//建立应用图标缓存器        --3.//建立LauncherModel        --4.//注册Intent.ACTION_PACKAGE_ADDED,Intent.ACTION_PACKAGE_REMOV...

centos7安装node方式整理记录~

为什么要写(copy)这个东西? 昨天想要安装一个node环境,搜到很多方法,但是好多地方因为某些原因无法安装成功,于是乎,我copy过来挨个做了尝试,不能正确安装的地方做了一点修改,做个记录; 如有侵权,请联系我,谢谢! 下面开始。。。 方法一.通过node版本管理工具nvm(Node version manager)安装; ①安装nvm1.1.安装n...

Java线程并发中常见的锁--自旋锁 偏向锁

随着互联网的蓬勃发展,越来越多的互联网企业面临着用户量膨胀而带来的并发安全问题。本文着重介绍了在java并发中常见的几种锁机制。 1.偏向锁 偏向锁是JDK1.6提出来的一种锁优化的机制。其核心的思想是,如果程序没有竞争,则取消之前已经取得锁的线程同步操作。也就是说,若某一锁被线程获取后,便进入偏向模式,当线程再次请求这个锁时,就无需再进行相关的同步操作...

Selenium Grid + Maven + TestNG + Jenkins 完成Selenium 分布式并发测试

Selenium Grid 是什么?   Selenium Grid 是一个可以方便的让你脚本运行在不同的平台以及不同的浏览器上的一个框架。Selenium Grid 分1和2两个版本,其中Selenium Grid 2的发布还晚于Selenium 2.0,也就是说Selenium Grid 2 并不是和Selenium 2.0 一起发布的,但是Selen...

java守护线程(后台线程)

/*1.让各个对象或类相互灵活交流2.两个线程都冻结了,就不能唤醒了,因为根据代码要一个线程活着才能执行唤醒操作,就像玩木游戏3.中断状态就是冻结状态4.当主线程退出的时候,里面的两个线程都处于冻结状态,这样就卡住了5.try catch   有异常,catch就自动帮忙处理,程序继续运行6.让wait 中断  就会发生异常,就会被处理*//*stop方法...

ios--进程/多线程/同步任务/异步任务/串行队列/并行队列(对比分析)

现在先说两个基本的概念,啥是进程,啥是线程,啥又是多线程;先把这两个总是给弄清再讲下面的 进程:正在进行的程序,我们就叫它进程. 线程:线程就是进程中的一个独立的执行路径.这句话怎么理解呢! 一个程序它是按顺序从上往下执行的, 这个执行顺序我们可以把它看成是一条线,把这条线就叫做线程(个人理解,错了勿喷);每一个程序中至少包含一条线程, 这条线程,我们叫它...