javascript中的伪线程,使用setTimeout模拟一个多线程

更新日期: 2018-08-08阅读量: 2999标签: 线程

浏览器的内核是多线程的,一个浏览器一般至少实现三个常驻线程: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引擎线程的最后执行。


例子:

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线程是完全没问题的,但过亿浏览器还是会蹦。(这里只是提供个简单的思路,其实过亿也可以不蹦)  


原文来源:https://segmentfault.com/a/1190000008723632

站长推荐

1.云服务推荐: 国内主流云服务商,各类云产品的最新活动,优惠券领取。地址:阿里云腾讯云华为云

链接: https://www.fly63.com/article/detial/999

Web Workers 到底是什么?

以前我们总说,JS是单线程没有多线程,当JS在页面中运行长耗时同步任务的时候就会导致页面假死影响用户体验,从而需要设置把任务放在任务队列中;执行任务队列中的任务也并非多线程进行的,然而现在HTML5提供了我们前端开发这样的能力

WebWorker进阶

篇文章主要分享介绍了WebWorker特殊应用场景, 扩展了WebWorker的能力, 为跨页面通信提供了另外一种思路。在上一篇文章里面也有了解到webworker与主线程之间的通信,使用的是一个PostMessage

JavaScript多线程编程

浏览器端JavaScript是以单线程的方式执行的,也就是说JavaScript和UI渲染占用同一个主线程,那就意味着,如果JavaScript进行高负载的数据处理,UI渲染就很有可能被阻断,浏览器就会出现卡顿,降低了用户体验。

理解JS执行顺序

众所周知,JS的执行顺序是自上而下的。 严格意义上来说,javascript没有多线程的概念,所有的程序都是单线程依次执行的。 就是代码在执行过程中,另一段代码想要执行就必须等当前代码执行完成后才可以进行。

Js多线程和Event Loop

几乎在每一本JS相关的书籍中,都会说JS是单线程的,JS是通过事件队列(Event Loop)的方式来实现异步回调的。 对很多初学JS的人来说,根本搞不清楚单线程的JS为什么拥有异步的能力,所以,我试图从进程、线程的角度来解释这个问题

浏览器中的 Event Loop

当我们执行 JS 代码的时候其实就是往执行栈中放入函数,那么遇到异步代码的时候该怎么办?其实当遇到异步的代码时,会被挂起并在需要执行的时候加入到 Task(有多种 Task) 队列中。一旦执行栈为空

聊聊 JavaScript 与浏览器的那些事 - 引擎与线程

对 JavaScript 解释器和浏览器的线程机制理解的不是特别透彻,很容易混淆浏览器多线程机制并错误认为由于 Web Worker 的设计使得 JavaScript 拥有了多线程的能力。事后搜了不少资料进行学习,整理成此文,主要介绍浏览器的各个引擎、线程间的工作机制以及 JavaScript 单线程的一些事。

如何理解JS的单线程?

JS本质是单线程的。也就是说,它并不能像JAVA语言那样,两个线程并发执行。 但我们平时看到的JS,分明是可以同时运作很多任务的,这又是怎么回事呢?

深入理解 Node.js 中的 Worker 线程

多年以来,Node.js 都不是实现高 CPU 密集型应用的最佳选择,这主要就是因为 JavaScript 的单线程。作为对此问题的解决方案,Node.js v10.5.0 通过 worker_threads 模块引入了实验性的 “worker 线程” 概念

进程切换与线程切换的区别?

注意这个题目问的是进程切换与线程切换的区别,不是进程与线程的区别。当然这里的线程指的是同一个进程中的线程。这个问题能很好的考察面试者对进程和线程的理解深度,有比较高的区分度。

点击更多...

内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!