• Web Worker在WebKit中的实现机制


        web worker 是执行在后台的 JavaScript,独立于其它脚本。不会影响页面的性能。这是HTML5的一个标准;实现上讲。浏览器为wokrer启动了新的线程,从而实现了异步操作的功能;  

        以下是woker的一个简单样例。在html页面中。以worker.js为源文件。创建了名为“worker”的Worker对象。通过worker.postMessage()接口向worker线程发送消息; worker线程将JSON格式化传递的两个数据相加后。再通过postMessage()接口将消息发送回页面js执行的主线程。 主线程再在onMessage()函数中处理woker线程发来的消息; 

    main.html

    <html>
      <head>
      <script type="text/javascript">
        var worker = new Worker('worker.js'); 
        var obj = {"first":1, "second":2};
        worker.postMessage(obj); 
        worker.onmessage = function (event) { 
          alert(event.data);
        }
    
        function postMsg(){
          if (worker)
            worker.postMessaage(obj); 
        }
      </script> 
      </head>
      <body>
         <button onclick="postMsg()">post</button>
      </body>
    </html>


    worker.js

     onmessage = function (event) 
     { 
        var data = event.data;
       var first=data.first;
       var second=data.second;
       handleTask(first,second); 
     }; 
    
     function  handleTask(a, b)
      {
        var out = a + b;
        postMessage("Worker Done! out = " + out);
      }
    


    WebKit载入并运行js的流程简单分成下面几步:

    1. 运行到"var worker = new Worker('worker.js')“时。在内核中构造WebCore::JSWorker对象(JSBbindings层)以及相应的WebCore::Worker对象(WebCore模块); 

    2.  构造JSWorker对象的过程中,依据初始化的url地址"worker.js"发起异步载入的流程; 

    3.  运行worker.postMessage()。向worker线程发送JSON格式化的消息数据; 由于这个时候。worker线程还没有创建,所以消息数据放在一个暂时消息队列中; 

    4. worker.js异步载入完毕后,创建并启动worker线程。并将暂时消息队列中的消息数据copy到woker相应的WorkerRunLoop的消息队列中; 

    5. worker线程创建完毕后。開始处理WorkerRunLoop的消息队列中所保存的消息; 

    6. woker线程发送消息到主线程。 

    7. 主线程收到worker线程发送的消息,运行onMessage(); 

    在经过一轮消息来回后,我们假设通过样例中button按钮来异步触发消息发送。那么步骤3的运行会有差别; 这个时候由于worker线程已经创建。所以消息会直接加入到WorkerRunLoop的消息队列中; 


    为了搞清楚整个实现机制,我们先来看一下WebKit内部worker相关的类。 当中Worker相应主页面JS中的'worker'对象(主线程中),而DedicatedWorkerThread表示worker线程; WorkerMessagingProxy关联了Worker对象与worker线程,从而实现主线程与worker线程之间的消息中转; DedicatedWorkerThread通过WorkerScriptController控制worker.js文件里的脚本在worker线程中的运行;浏览器会为worker线程创建一个独立的虚拟机环境(VM); 

     


    以下来看一下具体流程: 

    1. worker.js的异步载入步骤例如以下图,载入是在创建WebCore::JSWorker和WebCore::Worker对象的时候发起的。而且是异步载入的流程,不会堵塞兴许JS的运行,这也是为什么首次调用worker.postMessage()的时候。会出现worker线程还没有创建的情况; 



    2. worker线程的创建例如以下图所看到的。

    能够看出。当worker.js载入完毕后。WebKit会通过中转对象WorkerMessagingProxy创建DedicatedWorkerThread对象,并启动WorkerThread; WorkerMessagingProxy保持DedicatedWorkerThread对象的指针; 

      


    3.  主线程向worker线程发送消息的流程例如以下。当js运行到"worker.postMessage()“时,终于会通过JS主线程虚拟机映射到JSWorker::postMessage()函数,并通过中转对象WorkerMessagingProxy将消息加入到worker的消息队列。 假设worker线程在发送消息的时候,还没有创建。我们看到有个m_queueEarlyTasks对象会暂时保存当前消息,并在worker线程创建后再转移到正式的消息队列中; 否则。直接将消息加入到WorkerRunLoop管理的正式消息队列中; 

     


    4. worker线程中处理消息的流程例如以下。这就是worker.js中開始运行”onmessage()”的流程; 我们能够看到DedicatedWorkThread对象在自己的线程环境下的runLoop取出消息队列中的数据运行。而运行是通过EventTarget::dispatchEvent()分发并fire一个"message"类型的事件来实现的; 



    5. 下图是在worker线程中发送消息的流程,也是通过WorkerMessagingProxy来进行中传。最后会触发Document::postTask()函数,该函数实际上将Document::didReceiveTask()函数抛到主线程上去运行。 


    6. 下图是main线程上处理消息的流程, Document::didReceiveTask()在主线程上開始运行。终于也是通过dispatch并fire一个"message"类型的事件实现消息的处理。 

    。 


    所以总得来讲。woker的机制是通过中转对象实现消息的传递,再通过"message"事件完毕消息的处理; 

    (转载请注明出处:http://blog.csdn.net/codigger)

  • 相关阅读:
    hdu 1240 Asteroids!
    hdu 1253 胜利大逃亡
    hdu 1035 Robot Motion
    hdu 1181 变形课
    hdu 1548 A strange lift
    DFS Sum It Up
    hdu 3278 Catch That Cow
    hdu 1312 Red and Black
    ACM菜鸟
    eclipse新建安卓项目点击finish后窗口无法关闭
  • 原文地址:https://www.cnblogs.com/bhlsheji/p/5105154.html
Copyright © 2020-2023  润新知