指引网

当前位置: 主页 > 网页制作 > JavaScript >

javascript:多线程与伪线程

来源:网络 作者:佚名 点击: 时间:2017-08-07 22:13
[摘要] 浏览器的内核是多线程的,一个浏览器一般至少实现三个常驻线程:javascript引擎线程,GUI渲染线程,浏览器事件触发线程。

伪线程

重点:

浏览器的内核是多线程的,一个浏览器一般至少实现三个常驻线程:javascript引擎线程,GUI渲染线程,浏览器事件触发线程。

a.javascript引擎是基于事件驱动单线程执行的,JS引擎一直等待着任务队列中任务的到来,然后加以处理,浏览器无论什么时候都只有一个JS线程在运行JS程序。
b.GUI渲染线程负责渲染浏览器界面,当界面需要重排、重绘或由于某种操作引发回流时,该线程就会执行。但需要注意 GUI渲染线程与JS引擎是互斥的,当JS引擎执行时GUI线程会被挂起,GUI更新会被保存在一个队列中等到JS引擎空闲时立即被执行。
c.事件触发线程,当一个事件被触发时该线程会把事件添加到待处理队列的队尾,等待JS引擎的处理。这些事件可来自JavaScript引擎当前执行的代码块如setTimeOut、也可来自浏览器内核的其他线程如鼠标点击、AJAX异步请求等,但由于JS的单线程关系所有这些事件都得排队等待JS引擎处理。

当我们要循环过百万级的数据甚至亿的时候怎么办?
那就用setTimeout模拟一个多线程。
重点:js的工作机制是:当线程中没有执行任何同步代码的前提下才会执行异步代码,setTimeout是异步代码,所以setTimeout只能等js空闲才会执行,但死循环是永远不会空闲的,所以setTimeout也永远不会执行。即使setTimeout为0,他也是等js引擎的代码执行完之后才会插入到js引擎线程的最后执行。

上例子


 

  1. var thread = function () { 
  2.     var nowTime = 0, //线程已经执行了多久 
  3.         maxTime = 15;//线程最多执行多久 
  4.     var threadArr = [];//数组模拟线程队列 
  5.      
  6.     this.addThread = function (fn) { 
  7.         threadArr.push(fn) 
  8.     } 
  9.     this.start=function () { 
  10.         doingThread(); 
  11.     } 
  12.     var doingThread = function () { 
  13.         if (threadArr.length > 0) { 
  14.             if (nowTime < maxTime) { 
  15.                 let now = new Date().getTime(); 
  16.                 var method = threadArr[0]; 
  17.                 method(); 
  18.                 threadArr.splice(0, 1); 
  19.                 let nowNew = (new Date().getTime() - now); 
  20.                 nowTime += nowNew; 
  21.                 doingThread(); 
  22.             } else {//每执行完线程后睡1ms 
  23.                 nowTime=0; 
  24.                 setTimeout(doingThread, 1); 
  25.             } 
  26.         }else {//先睡着等待线程队列 
  27.             setTimeout(doingThread,100) 
  28.         } 
  29.     } 
  30. var fn = function (num) { 
  31.     console.log(num) 
  32.  
  33. var thread = new thread(); 
  34. thread.start() 
  35. for (let i = 0; i < 1000000; i++) { 
  36.     thread.addThread(function () { 
  37.         fn(i) 
  38.     }) 

循环百万级的数据量并且不阻塞Ui线程是完全没问题的,但过亿浏览器还是会蹦。(这里只是提供个简单的思路,其实过亿也可以不蹦)

------分隔线----------------------------