【JavaScript】JavaScript是多线程还是单线程?
之前在学浏览器渲染流程时了解的JavaScript是单线程执行的,时不时要考虑浏览器线程阻塞问题,然而又有人说JavaScript可以异步执行,比如setInterval、setTimeout以及Ajax等。那究竟是单线程还是多线程呢?
下图是浏览器所具有的线程:
单线程意味着,所有任务需要排队,前一个任务结束,才会执行后一个任务。如果前一个任务耗时很长,后一个任务就不得不一直等着。于是就有这么一个概念——任务队列。
首先我阐明下JavaScript是门同步的语言,上面我们通常所说的JavaScript的异步与其他语言的异步是不相同的,本质上还是同步。因为浏览器会有多个Queue存放异步通知,并且每个Queue的优先级也不同。JavaScript在执行代码时会产生一个执行栈,同步的代码在执行栈中,异步的在Queue中。有一个Event Loop会循环检查执行栈是否为空,为空时会在Queue中查看是否有需要处理的通知,有的话拿到执行栈中去执行。
JavaScript语言的设计者意识到,这时主线程完全可以不管IO设备,挂起处于等待中的任务,先运行排在后面的任务,等到IO设备返回了结果,再回过头,把挂起的任务继续执行下去。
于是,所有任务可以分为两种:一种是同步任务,一种是异步任务。
同步任务是指在主线程上排队执行的任务,只有前一个任务执行完毕,才能执行后一个任务;异步任务是指不进入主线程,而进入“任务队列”的任务,只有“任务队列”通知主线程,某个异步任务可以执行了,该任务才会进入主线程执行。
在HTML5之前,浏览器中的JavaScript的运行都是以单线程的方式工作的。虽然有多种方式实现了对多线程的模拟(例如:JavaScript中的setInterval方法,setTimeout方法等),但是在本质上程序的运行仍然是由JavaScript引擎以单线程调度的方式进行的。
在HTML5中引入的Web Worker使得浏览器端的JavaScript引擎可以并发地执行JavaScript代码,从而实现了对浏览器端多线程的良好支持。
所以,JavaScript是门单线程的语言,而其多线程的表现是属于浏览器的行为(JS引擎),他们之间没有冲突,更不是同一种事物。