Appearance
事件机制
什么是进程? 什么是线程
进程: 程序的一次执行,它占有一片独有的内存空间
线程: CPU 的基本调度单位,是程序执行的一个完成流程
进程与线程
- 一个进程中一般至少有一个运行的线程:主线程
- 一个进程中也可以同时运行多个线程。说明这个程序是多线程运行的。
- 一个进程内的数据可以供其他的多个线程共享
- 多个进程之间的数据不能直接共享。
- 线程池: 保存多个线程对象的容器,
多线程:
优点
- 能有效提升 CPU 的利用率
缺点
- 创建多线程开销
- 线程间切换开销
- 死锁和状态同步问题
单线程:
优点:
- 顺序编程简单易用
缺点:
- 效率低
JS 是单线程的(只是 JS 引擎是单线程运行的,但是会辅助如 GUI 渲染线程、异步线程、定时触发器线程、事件触发线程等去辅助执行)
为什么是单线程的?
因为如果多个线程间在同时操作同一个元素,那么如果一个线程在添加,一个线程在删除。那么就出现问题了。
可以多线程么?
H5 中的 Web Workers 可以开启多个线程,但是不能访问 DOM
浏览器运行时单线程还是多线程的?
多线程
浏览器运行时单进程还是多进程的?
单进程的: Firefox 老版 IE 多进程的: Chrome 新版 IE
浏览器相关
浏览器内核
不同浏览器的内核是不一样的:
Chrome|Safari : webkit firefox : Gecko IE : Trident 360+国内 : Trident + webkit
内核是由很多模块组成
主线程
- JS 引擎线程
- 即 JS 内核,负责处理 javascript 脚本程序(如 V8 引擎)。
- JS 引擎线程负责解析 javascript 脚本,执行代码。
- JS 引擎一直等待着任务队列中任务的到来,然后加以处理, 一个 Tab 页中无论什么时候都只有一个 JS 线程在运行 JS 程序(JS 是单线程的)
- 同样注意,GUI 渲染线程与 JS 引擎线程是互斥的,所以如果 JS 执行的时间过长,这样就会造成页面的渲染不连贯,导致页面渲染加载阻塞。
分线程
- GUI 渲染线程
- 负责渲染浏览器界面,解析 HTML、CSS、构建 DOM 树和 RenderObject 树、布局和绘制等。
- 当界面需要重绘或由于某种操作引发回流时,该线程会执行。
- 注意,GUI 渲染线程与 JS 引擎线程是互斥的,当 JS 引擎执行时 GUI 线程会被挂起,GUI 更新会被保存在一个队列中等到 JS 引擎空闲时立即执行。
- 定时触发器线程 : 负责定时器的管理
- 传说中的 setTimeout 和 setInterval 所在的线程。
- 浏览器定时器计数不是由 JS 引擎计数的(JS 是单线程的,如果处于阻塞线程状态就会影响计时器的计时准确),所以通过单独的线程来计时和触发回调(计时完毕后,将回调函数推到事件队列中,等待 JS 引擎空闲后执行)
- 注意,W3C 在 HTML 标准中规定,规定要求 setTimeout 中低于 4ms 的时间间隔算为 4ms。
- 事件触发线程 : 负责事件的管理
- 归属于浏览器而不是 JS 引擎,用来控制事件的循环(可以理解,JS 引擎自己都忙不过来了,当然需要浏览器另开线程协助)。
- 当 JS 引擎执行代码块如 setTimeout 时(当然也可以是其他线程,如鼠标点击、ajax 异步请求等),都会讲对应的任务添加到事件线程中,当对应的事件符合触发条件触发时,该线程会把事件添加到事件队列的队尾,等待 JS 引擎的处理。
- 注意,由于 JS 的单线程关系,所以这些待处理队列中的事件都得排队等待 JS 引擎处理(当 JS 引擎空闲时才会去执行)
- 异步 http 请求线程 : 负责 ajax 的请求
- 在 XMLHttpRequest 在连接后是通过浏览器新开一个线程请求
- 将检测到状态变更时,如果设置有回调函数,异步线程就产生状态变更事件,将这个回调再放入事件队列中。再由 JavaScript 引擎执行。
- Event Loop 轮询线程 : 负责轮询消息队列