zoukankan      html  css  js  c++  java
  • 对javascript 线程的理解

    今天和朋友讨论了一个js 线程的问题  千言不如一例 代码如下

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Document</title>
    </head>
    
    <script>
        function fun1() {
            setTimeout(function(){alert(1);},0)
            while(true) {};
        }
    </script>
    <body>
        <div id="div1">abc</div>
        <input type="button" value="测试" onclick="fun1();">
    </body>
    </html>

    如果按照以前js 顺序执行的思路来理解  那么点击测试按钮后 应该会先弹出alert(1) 然后死循环 (错 了)
    但是结果却是 点击按钮后直接死循环 

    出现這个问题的主要原因是对SetTimeout這个函数不清楚, 对javascript 单线程的理解不清楚造成的。

    首先我们对浏览器中的线程了解一下

     通常一个浏览器会至少存在三个线程:JS引擎线程(用于处理JS)、GUI渲染线程(用于页面渲染)、浏览器时间触发线程(用于控制交互)。 而因为JS可以操作DOM元素,进而会影响到GUI的渲染结果,因此JS引擎线程与GUI渲染线程是互斥的。也就是说当JS引擎线程处于运行状态时,GUI渲染线程将处于冻结状态。 JS引擎是基于事件驱动,采用的是单线程运行机制。即JS引擎会只会顺序的从任务列表中取任务,并执行。

     SetTimeout/SetInternal

        其中SetTiemout:在指定的毫秒数后调用指定的代码段;SetInternal:在指定的时间间隔内(ms)循环调用指定的代码段。这两个函数内都涉及到时间计数器,也就是都涉及到一个类似与MFC定时器。JS引擎本身就只能单线程运行,因此定时器需要由其他的外部线程来启动。所以对JS引擎而言,定时器线程可以被视为异步线程。但当定时器时间到达后,所触发的事件则必须在任务列表中排队,等候JS引擎的处理

    那么就不难理解了 

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Document</title>
    </head>
    
    <script>
        function fun1() {
            //--------任务1--------
            setTimeout(function(){alert(1);},0) //调用外部线程 后立即将代码push到js引擎的任务列表中 ---------任务2---------
            while(true) {};
        }
        //所以任务列表中的顺序应该是 
        //[
        //  任务1,--死循环 因为js非阻塞的机制 所以导致代码不会执行到任务2
        //  任务2
        //]
    </script>
    <body>
        <div id="dom1">abc</div>
        <input type="button" value="测试" onclick="fun1();">
    </body>
    </html>

    好了 铺垫已经打好了 接下来进入正题 dome操作也类似  

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Document</title>
    </head>
    
    <script>
        function fun1() {
            //--------任务1--------
            document.getElementById('dom1').innerHTML = 123; //因为操作了dome 所以得调用外部线程(GUI渲染线程)JS引擎线程与GUI渲染线程互斥 所以dome操作冻结 (可以理解为添加了一个任务2在S引擎的任务列表里面么?)-------任务2--------
    
            while(true) {}; //不需要调用外部线程 所以這个循环属于任务1
        }
        //所以任务列表中的顺序应该是 
        //[
        //  任务1,--死循环 因为js非阻塞的机制 所以导致代码不会执行到任务2
        //  任务2
        //]

    //最后有点疑问 如果我用debugger去调试的话 确会改变dom1的内容为123 然后才会进入循环???? </script> <body> <div id="dom1">abc</div> <input type="button" value="测试" onclick="fun1();"> </body> </html>

    setTimeout 的妙用

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Document</title>
    </head>
    
    <script>
        function fun1() {
            //--------任务1--------
            document.getElementById('dom1').innerHTML = 123; //因为操作了dome 所以得调用外部线程(GUI渲染线程)JS引擎线程与GUI渲染线程互斥 所以dome操作冻结 (可以理解为添加了一个任务2在S引擎的任务列表里面么? 任务列表Array.push(任务2) )-------任务2--------
    
            setTimeout(function(){while(true) {};},0); //调用外部线程 然后将触发的事件添加到任务列表中 -----任务3-----
        }
        //所以任务列表中的顺序应该是 
        //[
        //  任务1,
        //  任务2, --dome操作
        //  任务3, --循环
        //]
    </script>
    <body>
        <div id="dom1">abc</div>
        <input type="button" value="测试" onclick="fun1();">
    </body>
    </html>
  • 相关阅读:
    [转]进程的用户栈和内核栈
    什么是URL,URL格式
    设计灵感
    Spring源码学习相关记录
    HTML图片标签路径解析
    一次Spring Bean初始化顺序问题排查记录
    是要面向对象,还是简单粗暴?
    2018/07/26学习节点记录
    数据结构-堆 Java实现
    2018 ICPC 徐州邀请赛 总结
  • 原文地址:https://www.cnblogs.com/ElvinLong/p/4703458.html
Copyright © 2011-2022 走看看