这里就很少说了,主要说伪线程。由于web worker不能操做dom元素,不少时候用不上。javascript
重点:
浏览器的内核是多线程的,一个浏览器通常至少实现三个常驻线程:javascript引擎线程,GUI渲染线程,浏览器事件触发线程。java
a.javascript引擎是基于事件驱动单线程执行的,JS引擎一直等待着任务队列中任务的到来,而后加以处理,浏览器不管何时都只有一个JS线程在运行JS程序。
b.GUI渲染线程负责渲染浏览器界面,当界面须要重排、重绘或因为某种操做引起回流时,该线程就会执行。但须要注意 GUI渲染线程与JS引擎是互斥的,当JS引擎执行时GUI线程会被挂起,GUI更新会被保存在一个队列中等到JS引擎空闲时当即被执行。
c.事件触发线程,当一个事件被触发时该线程会把事件添加到待处理队列的队尾,等待JS引擎的处理。这些事件可来自JavaScript引擎当前执行的代码块如setTimeOut、也可来自浏览器内核的其余线程如鼠标点击、AJAX异步请求等,但因为JS的单线程关系全部这些事件都得排队等待JS引擎处理。web
当咱们要循环过百万级的数据甚至亿的时候怎么办?
那就用setTimeout模拟一个多线程。
重点:js的工做机制是:当线程中没有执行任何同步代码的前提下才会执行异步代码,setTimeout是异步代码,因此setTimeout只能等js空闲才会执行,但死循环是永远不会空闲的,因此setTimeout也永远不会执行。即便setTimeout为0,他也是等js引擎的代码执行完以后才会插入到js引擎线程的最后执行。
上栗子数组
var thread = function () { var nowTime = 0, //线程已经执行了多久 maxTime = 15;//线程最多执行多久 var threadArr = [];//数组模拟线程队列 this.addThread = function (fn) { threadArr.push(fn) } this.start=function () { doingThread(); } var doingThread = function () { if (threadArr.length > 0) { if (nowTime < maxTime) { let now = new Date().getTime(); var method = threadArr[0]; method(); threadArr.splice(0, 1); let nowNew = (new Date().getTime() - now); nowTime += nowNew; doingThread(); } else {//每执行完线程后睡1ms nowTime=0; setTimeout(doingThread, 1); } }else {//先睡着等待线程队列 setTimeout(doingThread,100) } } } var fn = function (num) { console.log(num) } var thread = new thread(); thread.start() for (let i = 0; i < 1000000; i++) { thread.addThread(function () { fn(i) }) }
循环百万级的数据量而且不阻塞Ui线程是彻底没问题的,但过亿浏览器仍是会蹦。(这里只是提供个简单的思路,其实过亿也能够不蹦)浏览器