单线程

单线程是JavaScript语言的一大特色。

单线程,也就是同一时间只能做一件事情。

但是为什么是单线程呢?

因为作为浏览器脚本语言,JavaScript的主要用途是与用户互动,以及操作DOM。如果JS是多线程的话,两个线程同时对DOM进行操作,会出现冲突,所以为了避免冲突、提高效率,JS为单线程语言。

H5添加了webworkers多线程,是不是打破了JS是单线程的本质?

为了利用多核CPU的计算能力,H5提出Web Worker标准,允许JS脚本创建多个线程,但是子线程完全受主线程控制,且不得操作DOM。所以,这个新标准并没有改变JavaScript单线程的本质。

任务队列

同步任务队列(Synchronous)

在主线程上排队执行的任务,只有前一个任务执行完毕,才能执行后一个任务

异步任务队列(Asynchronous)

不进入主线程,而是进入异步任务队列(Asynchronous Task Queue),只有当同步任务执行完毕,且轮到异步任务才会进入主

线程执行。

事件轮询(Event Loop)

(1)所有同步任务都在主线程上执行,形成一个执行栈(execution context stack)。

(2)执行栈上的同步任务执行完毕后。只要异步任务有了运行结果,就在异步任务队列中放置一个事件。

(3)一旦"执行栈"中的所有同步任务执行完毕,系统就会读取异步任务队列,看看里面有哪些事件。

        那些对应的异步任务,于是结束等待状态,进入执行栈,开始执行。

(4)主线程不断重复上面的第三步。

实例演示

demo代码如下:

console.log(1);//同步任务
setTimeout(function() {
   console.log(2);//异步任务
}, 100);
setTimeout(function() {
   console.log(3);//异步任务
});
console.log(4);//同步任务

执行结果:大家也知道,是1、4、3、2

1. 首先把任务分类,console.log(1);放入同步任务队列;

2. 然后两个setTimeout一个等待100ms、一个是立即执行,所以function() {console.log(3);}会先于function() {console.log(2);}

    放入异步队列中,而function() {console.log(2);}会在100ms后放入异步队列中;

3. 最后console.log(4);放在放入同步任务队列;

4. 当同步任务执行完毕后,浏览器引擎回到异步队列中看里面有没有待执行的函数,如果有,则立即执行;没有,则一直

    监听着。由于计算机执行速度是毫秒级的,所以100ms对它来说事件很长,当它执行完第一个异步任务时,第二个异步任务还

    没进来。要等到100ms结束后,第二个任务进来,才能马上执行。再次期间,引擎一直在进行着轮询的工作。

10-07 12:30