基本概念

1、js的执行过程是单线程的模式,也就是同步进行,只有前面的代码执行完了才会往下面执行

2、但是执行js代码也只是浏览器的线程之一所负责的事情,这个线程被称为js引擎,浏览器还具有其他线程:界面渲染线程(UI)、浏览器事件触发线程(控制交互,响应用户)、http请求线程(处理请求,而ajax发送请求则会委托浏览器新开一个http线程)、EventLoop轮询线程(负责轮询消息队列)

3、浏览器中js代码的作用:执行JavaScript代码 、对用户的输入(包含鼠标点击、键盘输入等等)做出反应 、处理异步的网络请求

js单线程

1、单线程的含义是js只能在一个线程上运行,也就说,js同时只能执行一个js任务,其它的任务则会排队等待执行。

2、js是单线程的,并不代表js引擎线程只有一个。js引擎有多个线程,一个主线程,其它的后台配合主线程。

3、多线程之间会共享运行资源,浏览器端的js会操作dom,多个线程必然会带来同步的问题,所有js核心选择了单线程来避免处理这个麻烦。js可以操作dom,影响渲染,所以js引擎线程和UI线程是互斥的。这也就解释了js执行时会阻塞页面的渲染

js消息队列

1、JavaScript运行时,除了一个运行线程,引擎还提供一个消息队列,里面是各种需要当前程序处理的消息。新的消息进入队列的时候,会自动排在队列的尾端

2、单线程意味着js任务需要排队,如果前一个任务出现大量的耗时操作,后面的任务得不到执行,任务的积累会导致页面的“假死”。这也是js编程一直在强调需要回避的“坑”

js执行任务方式

1、首先js任务分两种:同步任务、异步任务

2、同步任务:在主线程排队支持的任务,前一个任务执行完毕后,执行后一个任务,形成一个执行栈,线程执行时在内存形成的空间为栈,进程形成堆结构,这是内存的结构。执行栈可以实现函数的层层调用。注意不要理解成同步代码进入栈中,按栈的出栈顺序来执行。

3、异步任务:会被主线程挂起,不会进入主线程,而是进入消息队列,而且必须指定回调函数,只有消息队列通知主线程,并且执行栈为空时,该消息对应的任务才会进入执行栈获得执行的机会。

4、主线程说明:

(1)所有同步任务都在主线程上执行,形成一个执行栈。 
(2)主线程之外,还存在一个”任务队列”(消息队列)。只要异步任务有了运行结果,就在”任务队列”之中放置一个事件。 
(3)一旦”执行栈”中的所有同步任务执行完毕,系统就会读取”任务队列”(消息队列),看看里面有哪些事件。那些对应的异步任务,于是结束等待状态,进入执行栈,开始执行。 
(4)主线程不断重复上面的第三步。

5、消息队列说明:

(1)消息队列队列(或者叫任务队列)是一个事件的队列,IO响应时(鼠标点击等输入输出设备的操作),会往队列中添加一个消息,此时说明相关的异步代码到了执行的时机,可以进入主线程的执行栈了。

(2)主线程读取消息队列,可以读取到对应的事件。

(3)消息队列可以响应IO事件,还有用户产生的事件(比如点击鼠标,页面滚动),只要指定了回调函数,就会进入消息队列,等待EventLoop轮询线程处理,是否可以进入主线程的执行栈。

(4)消息和回调函数相互联系的含义:主线程读到消息,就会执行相应的回调函数;进入消息队列的消息,必须对应相应的回调函数,否则这个消息会被丢弃不会进入消息队列。

(5)消息队列是一个先进先出的队列结构,这就决定了它的执行顺序,先产生的消息会被主线程先读取,会不会执行则会先检查一下执行时间,因为存在setTimeout等定时函数,这类事件产生的消息进入到消息队列,被执行的时机取决与它在队列中的位置和执行时间有关。【使用setTimeout能够避免阻塞UI线程就是这个原因】。

5、需要注意的是:执行栈中的代码(同步任务),总是在读取”任务队列”(异步任务)之前执行。

EventLoop

1、主线程从”任务队列”中读取事件,这个过程是循环不断的,所以整个的这种运行机制又称为Event Loop(事件循环)。

2、简单说,浏览器的两个线程:一个负责程序本身的运行,称为”主线程”;另一个负责主线程与其他进程(主要是各种I/O操作)的通信,被称为”Event Loop线程”(可以译为”消息线程”)。

3、由于js是运行在单线程上的,所有浏览器单独开启一个线程来处理事件消息的轮询,避免阻塞js的执行。

异步代码执行逻辑

1、每当遇到I/O的时候,主线程就让EventLoop线程去通知相应的I/O程序,然后接着往后运行,所以不存在等待时间。等到I/O程序完成操作,EventLoop线程把消息添加到消息队列,主线程就调用事先设定的回调函数,完成整个任务。

2、js的ajax是new XMLHttpRequest()对象实现的,浏览器会新开一个线程来处理http请求,这就是ajax能够实现局部刷新的同时,还能响应用户交互的原因。

定时器

1、前面也提到了定时器,定时器是会在进入消息队列,这也就和异步代码的执行逻辑一样了。它在”消息队列”的尾部添加一个消息,因此要等到同步任务和”消息队列”现有的任务都处理完,才会得到执行的机会,还要看定时器设置的时间是否到了才会执行。

<script>
for(var i = 0 ; i < 10; i++){
setTimeout(function(){
console.log(i);//打印10次10
},0);
}
</script>

所以,只有等到主线程的任务执行完之后,setTimeout中的事件才会被执行,虽然时间间隔是0秒,但是必须等主线程任务完成,所以最后打印的都是10

2、可以用闭包来解决问题,每次执行for循环的时候,把函数作为返回值给setTimeout作为参数,函数里面存着从for循环里面拿到的每一个值,下面代码会返回多个函数,每个函数的j值都不一样

<script>
for(var i = 0; i< 3; i++){
function foo(j){
// var j;
// j = 实参
//j = i
return function(){
console.log(j);
};
}
//0
var f = foo(i);
setTimeout(f, 0);
}
</script>

参考:

http://blog.csdn.net/w2765006513/article/details/53743051

https://www.cnblogs.com/haodawang/articles/5850822.html

JS高级——浏览器的线程的更多相关文章

  1. js高级-浏览器事件循环机制Event Loop

    JavaScript 是队列的形式一个个执行的 同一时间只能执行一段代码,单线程的  (队列的数据结构) 浏览器是多线程的 JavaScript执行线程负责执行js代码 UI线程负责UI展示的 Jav ...

  2. JS高级(摘自简书)

    JS高级 1. 访问对象属性(方法也是属性)的通用方式:obj['属性名'] 1. 属性名包含特殊字符,如"-".空格,访问:obj['content-type'] 2. 属性名不 ...

  3. 前端进阶试题css(来自js高级前端开发---豪情)既然被发现了HOHO,那我就置顶了嘿嘿!觉得自己技术OK的可以把这套题目做完哦,然后加入高级前端的社区咯

    http://www.cnblogs.com/jikey/p/4426105.html js高级前端开发加群方法(此群很难进,里面纯技术,严禁广告,水群) 完整题目做完发邮箱(jikeytang@16 ...

  4. js高级程序设计笔记之-addEventListener()与removeEventListener(),事件解除与绑定

    js高级程序设计笔记之-addEventListener()与removeEventListener(),事件解除与绑定 addEventListener()与removeEventListener( ...

  5. 惰性函数——JS高级

    我们先来看一下js的异步提交. XHR我们在原生的时候常常用到,因为常用到,我们更多把封装到了工具库中 先看下他最常用的实现 // 旧方法 function createXHR() { var xhr ...

  6. 《Node.js 高级编程》简介与第二章笔记

    <Node.js 高级编程> 作者简介 Pedro Teixerra 高产,开源项目程序员 Node 社区活跃成员,Node公司的创始人之一. 10岁开始编程,Visual Basic.C ...

  7. Ext.js高级组件

    第二章:Ext.js高级组件 grid组件 普通方式 表格面板类Ext.grid.Panel xtype(别名):gridpanel.grid title标题.renderTo渲染至.width宽.h ...

  8. JS高级学习历程-1

    JS高级-34-昨天内容回顾     时间:2015-5-11 1.DOM获取元素节点 document.getElenmentById(id 属性值)                         ...

  9. JS高级---构造函数通过原型添加方法,原型的作用: 共享数据, 节省内存空间

    JS高级---构造函数,通过原型添加方法,原型的作用: 共享数据, 节省内存空间 构造函数 //构造函数 function Person(sex, age) { this.sex = sex; thi ...

随机推荐

  1. 【Chrome】Chrome浏览器怎么查看版本信息

    第一步,打开Chrome浏览器 第二步,弹出浏览器主界面 第三步,点击右上按钮(三横杠) 第四步,下拉中选择“关于” 第五步,弹出窗口,可以看到版本信息 第二种方法: 第六步,也可以通过地址栏里输入命 ...

  2. Win32编程API 基础篇 -- 6.菜单和图标

    菜单和按钮 例子:菜单1 本小节仅仅向你展示如果向你的窗口中加入一个基本的菜单,通常你会用到一个提前制作好的菜单资源,这会是一份.rc文件并且会被编译链接进你的.exe可执行程序中.这是具体的流程做法 ...

  3. 洛谷—— P1419 寻找段落

    https://www.luogu.org/problem/show?pid=1419 题目描述 给定一个长度为n的序列a_i,定义a[i]为第i个元素的价值.现在需要找出序列中最有价值的“段落”.段 ...

  4. Spring实现封装自定义注解@Trimmed清除字符串前后的空格

    在Spring中实现字符串清除的方法有很多,原生方法String自带trim()方法,或者使用StringUtils提供的trim...方法. 通常可以将上面的方式封装成自定义注解的形式去实现来节省更 ...

  5. MyBatis3-实现单表数据的增删查改

    继续前一篇文章http://www.cnblogs.com/EasonJim/p/7050710.html所示的例子,返回的是单个实体,而接下来将进行列表的返回等操作: 一.查询列表 查询出列表,也就 ...

  6. Oracle Multitenant Environment (五) Create PDB

    Creating and Removing PDBs with SQL*Plus This chapter contains the following topics: About Creating ...

  7. fastjson将java list转为json字符串

    1.直接用fastjson的静态方法string JSON.toJSONString(list)方法就行,JSON.toJSONString(list)将java list转为json字符串. 2.t ...

  8. 去除ckeditor上传图片预览中的英文字母

    去除ckeditor上传图片预览中的英文字母 CKEDITOR.replace('text', { filebrowserImageUploadUrl : 'upload_img.do', langu ...

  9. Python3基础(十二) 学习总结·附PDF

    Python是一门强大的解释型.面向对象的高级程序设计语言,它优雅.简单.可移植.易扩展,可用于桌面应用.系统编程.数据库编程.网络编程.web开发.图像处理.人工智能.数学应用.文本处理等等. 在学 ...

  10. Project Euler:Problem 42 Coded triangle numbers

    The nth term of the sequence of triangle numbers is given by, tn = ½n(n+1); so the first ten triangl ...