第四章 线程机制和事件机制
4.1 进程和线程
进程:
程序的一次执行, 它占有一片独有的内存空间
线程:
CPU的基本调度单位, 是程序执行的一个完整流程
进程和线程:
* 一个进程中一般至少有一个运行的线程: 主线程。
* 一个进程中也可以同时运行多个线程, 我们会说程序是多线程运行的。
* 一个进程内的数据可以供其中的多个线程直接共享。
* 多个进程之间的数据是不能直接共享的。
4.2 JavaScript是单线程执行
1. 如何证明JavaScript是单线程执行?
设置了定时器,定时器的回调函数会等到主线程空闲且时间到执行;
如果主线程没有空闲下来,即使定时器的时间到了,回调函数也不会执行(等到主线程空闲)。
2. 为什么JavaScript选择单线程?
多线程会有线程调度以及线程开启关闭的开销
JavaScript主要在浏览器端操作DOM完成特效,如果不是单线程,不好解决页面渲染的同步问题。
4.3 事件轮询(循环)机制
事件轮询(Event Loop)是 JS 实现异步的具体解决方案,同步代码直接执行,异步函数或代码块先放在异步队列中,待同步函数执行完毕,轮询执行异步队列的函数。
执行栈(调用栈): 要执行的代码进入执行栈
回调队列: 计时器过期或者事件触发亦或者接收到ajax响应,现在回调被推送到回调队列。但是回调不会立即执行,这就是事件轮询开始的地方。
管理模块: DOM事件管理、定时器管理、ajax请求管理
事件轮询: 事件轮询的工作是监听执行堆栈,并确定执行堆栈是否为空。如果执行堆栈是空的,它将检查回调队列,看看是否有任何挂起的回调等待执行。
一道经典题目:
//问题描述:请写出最终的输出值,并解释原因
var value1 = 0, value2 = 0, value3 = 0;
for ( var i = 1; i <= 3; i++) {
var i2 = i;
(function() {
var i3 = i;
setTimeout(function() {
value1 += i;
value2 += i2;
value3 += i3;
}, 1);
})();
}
setTimeout(function() {
console.log(value1, value2, value3);
}, 100);
4.4 JS多线程
利用Worker可以实现多线程运算符
通过实例化一个Worker,创建一个子线程
子线程里面不允许操作DOM,也没有window
worker适合场景:
把耗时的计算放在分线程,不会影响主线程的其他工作
如果耗时的计算在主线程,导致页面卡顿(甚至崩溃)
worker的缺点:
① 无法操作DOM
② 无法跨域
③ 兼容性(不是所有的浏览器都可以使用)
Worker 构造函数
Worker.prototype.postMessage() 向分线程发送数据
Worker.prototype.onmessage 监听分线程的消息