精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

深入HTML5應用實踐:多線程編程

開發 后端 前端
W3C 在 HTML5 的規范中提出了工作線程(Web Worker)的概念,工作線程允許開發人員編寫能夠長時間運行而不被用戶所中斷的后臺程序, 去執行事務或者邏輯,并同時保證頁面對用戶的及時響應。本文深入 HTML5 多線程規范,講述多線程實現原理、方法,同時以實例的形式講解 HTML5 中多線程編程以及應用。

HTML5 中工作線程(Web Worker)簡介

至 2008 年 W3C 制定出第一個 HTML5 草案開始,HTML5 承載了越來越多嶄新的特性和功能。它不但強化了 Web 系統或網頁的表現性能,而且還增加了對本地數據庫等 Web 應用功能的支持。其中,最重要的一個便是對多線程的支持。在 HTML5 中提出了工作線程(Web Worker)的概念,并且規范出 Web Worker 的三大主要特征:能夠長時間運行(響應),理想的啟動性能以及理想的內存消耗。Web Worker 允許開發人員編寫能夠長時間運行而不被用戶所中斷的后臺程序,去執行事務或者邏輯,并同時保證頁面對用戶的及時響應。本文深入 HTML5 多線程規范,講述多線程實現原理、方法,同時以實例的形式講解 HTML5 中多線程編程以及應用。

W3C 中的工作線程規范到目前為止已經定義了出了一系列公共接口,它允許 Web 程序開發人員去創建后臺線程在他們的主頁面中并發的運行腳本。這將使得線程級別的消息通信成為現實。

詳解 HTML5 工作線程原理

傳統上的線程可以解釋為輕量級進程,它和進程一樣擁有獨立的執行控制,一般情況下由操作系統負責調度。而在 HTML5 中的多線程是這樣一種機制,它允許在 Web 程序中并發執行多個 JavaScript 腳本,每個腳本執行流都稱為一個線程,彼此間互相獨立,并且有瀏覽器中的 JavaScript 引擎負責管理。下面我們將詳細講解 HTML5 的工作線程原理。

工作線程與多線程編程

在 HTML5 中,工作線程的出現使得在 Web 頁面中進行多線程編程成為可能。眾所周知,傳統頁面中(HTML5 之前)的 JavaScript 的運行都是以單線程的方式工作的,雖然有多種方式實現了對多線程的模擬(例如:JavaScript 中的 setinterval 方法,setTimeout 方法等),但是在本質上程序的運行仍然是由 JavaScript 引擎以單線程調度的方式進行的。在 HTML5 中引入的工作線程使得瀏覽器端的 JavaScript 引擎可以并發地執行 JavaScript 代碼,從而實現了對瀏覽器端多線程編程的良好支持。

HTML5 中的 Web Worker 可以分為兩種不同線程類型,一個是專用線程 Dedicated Worker,一個是共享線程 Shared Worker。兩種類型的線程各有不同的用途。下面對這兩種工作線程作了詳細的說明和描述。

專用線程:Dedicated Worker

1. 專用線程(dedicated worker)的創建方式:

在創建專用線程的時候,需要給 Worker 的構造函數提供一個指向 JavaScript 文件資源的 URL,這也是創建專用線程時 Worker 構造函數所需要的唯一參數。當這個構造函數被調用之后,一個工作線程的實例便會被創建出來。下面是創建專用線程代碼示例:

  • 清單 1. 創建專用線程示例代碼
  1. var worker = new Worker('dedicated.js');  

2. 與一個專用線程通信:

專用線程在運行的過程中會在后臺使用 MessagePort 對象,而 MessagePort 對象支持 HTML5 中多線程提供的所有功能,例如:可以發送和接受結構化數據(JSON 等),傳輸二進制數據,并且支持在不同端口中傳輸數據等。

為了在頁面主程序接收從專用線程傳遞過來的消息,我們需要使用工作線程的 onmessage 事件處理器,定義 onmessage 的實例代碼如下:

  •  清單 2. 接收來至工作線程示例代碼
  1. worker.onmessage = function (event) { ... };    

3.另外,開發人員也可以選擇使用 addEventListener 方法,它最終的實現方式和作用和 onmessage 相同。

   就像前面講述的,專用線程會使用隱式的 MessagePort 實例,當專用線程被創建的時候,MessagePort 的端口消息隊列便被主動啟用。因此,這也和工作線程接口中定義的 start 方法作用一   致。

    如果要想一個專用線程發送數據,那么我們需要使用線程中的 postMessage 方法。專用線程不僅僅支持傳輸二進制數據,也支持結構化的 JavaScript 數據格式。在這里有一點需要注意,為了高效地傳輸 ArrayBuffer 對象數據,需要在 postMessage 方法中的第二個參數中指定它。實例代碼如下:

  • 清單 3. 高效的發送 ArrayBuffer 數據代碼
  1. worker.postMessage({ operation: 'list_all_users',   
  2. //ArrayBuffer object     
  3. input: buffer,     threshold: 0.8,    }, [buffer]);    

共享線程 Shared Worker

1.共享線程

共享線程可以由兩種方式來定義:一是通過指向 JavaScript 腳本資源的 URL 來創建,而是通過顯式的名稱。當由顯式的名稱來定義的時候,由創建這個共享線程的第一個頁面中使用 URL 會被用來作為這個共享線程的 JavaScript 腳本資源 URL。通過這樣一種方式,它允許同域中的多個應用程序使用同一個提供公共服務的共享線程,從而不需要所有的應用程序都去與這個提供公共服務的 URL 保持聯系。

無論在什么情況下,共享線程的作用域或者是生效范圍都是由創建它的域來定義的。因此,兩個不同的站點(即域)使用相同的共享線程名稱也不會沖突。

 

2.共享線程的創建

創建共享線程可以通過使用 SharedWorker() 構造函數來實現,這個構造函數使用 URL 作為第一個參數,即是指向 JavaScript 資源文件的 URL,同時,如果開發人員提供了第二個構造參數,那么這個參數將被用于作為這個共享線程的名稱。創建共享線程的代碼示例如下:

  1. / 從端口接收數據 , 包括文本數據以及結構化數據 1. worker.port.onmessage = function (event) { define your logic here... };  // 向端口發送普通文本數據  
  2.  
  3. worker.port.postMessage('put your message here … ');  // 向端口發送結構化數據  
  4.  worker.port.postMessage({ username: 'usertext'; live_city:  ['data-one', 'data-two', 'data-three','data-four']});

 

3.與共享線程通信

共享線程的通信也是跟專用線程一樣,是通過使用隱式的 MessagePort 對象實例來完成的。當使用 SharedWorker() 構造函數的時候,這個對象將通過一種引用的方式被返回回來。我們可以通過這個引用的 port 端口屬性來與它進行通信。發送消息與接收消息的代碼示例如下:

  • 清單 4. 發送消息與接收消息代碼

上面示例代碼中,第一個我們使用 onmessage 事件處理器來接收消息,第二個使用 postMessage 來發送普通文本數據,第三個使用 postMessage 來發送結構化的數據,這里我們使用了 JSON 數據格式。

工作線程事件處理模型

當工作線程被一個具有 URL 參數的構造函數創建的時候,它需要有一系列的處理流程來處理和記錄它本身的數據和狀態。下面我們給出了工作線程的處理模型如下(注:由于 W3C 中工作線程的規范依然在更新,您讀到這篇文章的時候可能看到已不是最新的處理模型,建議參考 W3C 中的最新規范):

1. 創建一個獨立的并行處理環境,并且在這個環境里面異步的運行下面的步驟。

2. 如果它的全局作用域是 SharedWorkerGlobalScope 對象,那么把最合適的應用程序緩存和它聯系在一起。

3. 嘗試從它提供的 URL 里面使用 synchronous 標志和 force same-origin 標志獲取腳本資源。

4. 新腳本創建的時候會按照下面的步驟:

  1. 創建這個腳本的執行環境。
  2. 使用腳本的執行環境解析腳本資源。
  3. 設置腳本的全局變量為工作線程全局變量。
  4. 設置腳本編碼為 UTF-8 編碼。

5. 啟動線程監視器,關閉孤兒線程。

6. 對于掛起線程,啟動線程監視器監視掛起線程的狀態,即時在并行環境中更改它們的狀態。

7. 跳入腳本初始點,并且啟動運行。

8. 如果其全局變量為 DedicatedWorkerGlobalScope 對象,然后在線程的隱式端口中啟用端口消息隊列。

9. 對于事件循環,等待一直到事件循環列表中出現新的任務。

10. 首先運行事件循環列表中的最先進入的任務,但是用戶代理可以選擇運行任何一個任務。

11. 如果事件循環列表擁有存儲 mutex 互斥信號量,那么釋放它。

12. 當運行完一個任務后,從事件循環列表中刪除它。

13. 如果事件循環列表中還有任務,那么繼續前面的步驟執行這些任務。

14. 如果活動超時后,清空工作線程的全局作用域列表。

15. 釋放工作線程的端口列表中的所有端口。

#p#

工作線程應用范圍和作用域

工作線程的全局作用域僅僅限于工作線程本身,即在線程的生命周期內有效。規范中 WorkerGlobalScope 接口代表了它的全局作用域,下面我們來看下這個接口的具體實施細節(WorkerGlobalScope 抽象接口)。

  • 清單 5. WorkerGlobalScope 抽象接口代碼
  1. interface WorkerGlobalScope {   
  2. readonly attribute WorkerGlobalScope self;   
  3. readonly attribute WorkerLocation location;    
  4. void close();            attribute Function onerror;  
  5. };  
  6. WorkerGlobalScope implements WorkerUtils;  
  7. WorkerGlobalScope implements EventTarget;   

我們可以使用 WorkerGlobalScope 的 self 屬性來或者這個對象本身的引用。location 屬性返回當線程被創建出來的時候與之關聯的 WorkerLocation 對象,它表示用于初始化這個工作線程的腳步資源的絕對 URL,即使頁面被多次重定向后,這個 URL 資源位置也不會改變。

當腳本調用 WorkerGlobalScope 上的 close()方法后,會自動的執行下面的兩個步驟:

1. 刪除這個工作線程事件隊列中的所有任務。

2. 設置 WorkerGlobalScope 對象的 closing 狀態為 true (這將阻止以后任何新的任務繼續添加到事件隊列中來)。

工作線程生命周期

工作線程之間的通信必須依賴于瀏覽器的上下文環境,并且通過它們的 MessagePort 對象實例傳遞消息。每個工作線程的全局作用域都擁有這些線程的端口列表,這些列表包括了所有線程使用到的 MessagePort 對象。在專用線程的情況下,這個列表還會包含隱式的 MessagePort 對象。

每個工作線程的全局作用域對象 WorkerGlobalScope 還會有一個工作線程的線程列表,在初始化時這個列表為空。當工作線程被創建的時候或者擁有父工作線程的時候,它們就會被填充進來。

最后,每個工作線程的全局作用域對象 WorkerGlobalScope 還擁有這個線程的文檔模型,在初始化時這個列表為空。當工作線程被創建的時候,文檔對象就會被填充進來。無論何時當一個文檔對象被丟棄的時候,它就要從這個文檔對象列舉里面刪除出來。

在工作線程的生命周期中,定義了下面四種不同類型的線程名稱,用以標識它們在線程的整個生命周期中的不同狀態:

  • 當一個工作線程的文檔對象列舉不為空的時候,這個工作線程會被稱之為許可線程。(A worker is said to be a permissible worker if its list of the worker's Documents is not empty.)
  • 當一個工作線程是許可線程并且或者擁有數據庫事務或者擁有網絡連接或者它的工作線程列表不為空的時候,這個工作線程會被稱之為受保護的線程。(A worker is said to be a protected worker if it is a permissible worker and either it has outstanding timers, database transactions, or network connections, or its list of the worker's ports is not empty)
  • 當一個工作線程的文檔對象列表中的任何一個對象都是處于完全活動狀態的時候,這個工作線程會被稱之為需要激活線程。(A worker is said to be an active needed worker if any of the Document objects in the worker's Documents are fully active.)
  • 當一個工作線程是一個非需要激活線程同時又是一個許可線程的時候,這個工作線程會被稱之為掛起線程。(A worker is said to be a suspendable worker if it is not an active needed worker but it is a permissible worker.)

由于 W3C 的 Web Worker 規范目前還是處于完善階段,沒有形成最終的規范,本文也將上面線程的四種不同狀態的原文定義附在了后面。

工作線程(Web Worker)API 接口

類庫和腳本的訪問和引入

對于類庫和腳本的訪問和引入,規范中規定可以使用 WorkerGlobalScope 對象的 importScripts(urls) 方法來引入網絡中的腳本資源。當用戶調用這個方法引入資源的時候會執行下面的步驟來完成這個操作:

  1. 如果沒有給 importScripts 方法任何參數,那么立即返回,終止下面的步驟。
  2. 解析 importScripts 方法的每一個參數。
  3. 如果有任何失敗或者錯誤,拋出 SYNTAX_ERR 異常。
  4. 嘗試從用戶提供的 URL 資源位置處獲取腳本資源。
  5. 對于 importScripts 方法的每一個參數,按照用戶的提供順序,獲取腳本資源后繼續進行其它操作。
  • 清單 6. 外部資源腳本引入和訪問示例代碼
  1. /**  
  2.  * 使用 importScripts 方法引入外部資源腳本,在這里我們使用了數學公式計算工具庫 math_utilities.js  
  3.  * 當 JavaScript 引擎對這個資源文件加載完畢后,繼續執行下面的代碼。同時,下面的的代碼可以訪問和調用 
  4.  * 在資源文件中定義的變量和方法。 
  5.  **/  
  6.  
  7. importScripts('math_utilities.js');   
  8. /**  * This worker is used to calculate  * the least common multiple  * and the greatest common divisor  */  
  9. onmessage = function (event)  {  
  10. var first=event.data.first;  var second=event.data.second;  calculate(first,second);  };    
  11. /*  * calculate the least common multiple  * and the greatest common divisor  */  
  12. function calculate(first,second) {     
  13. //do the calculation work  var common_divisor=divisor(first,second);  
  14. var common_multiple=multiple(first,second);     
  15. postMessage("Work done! " +  The least common multiple is "+common_divisor  +" and the greatest common divisor is "+common_multiple);  }   

工作導航器對象(WorkerNavigator)

在 HTML5 中, WorkerUtils 接口的 navigator 屬性會返回一個工作導航器對象(WorkerNavigator),這個對象定義并且代表了用戶代理(即 Web 客戶端)的標識和狀態。因此,用戶和 Web 腳本開發人員可以在多線程開發過程中通過這個對象來取得或者確定用戶的狀態。

  1. 工作導航器對象(WorkerNavigator)

    WorkerUtils 抽象接口的 navigator 屬性會返回一個 WorkerNavigator 用戶接口,用于用戶代理的識別的狀態標識。我們來看下 WorkerNavigator 接口的定義。

  2. WorkerNavigator 接口定義

    清單 7. WorkerNavigator 接口定義代碼
    1. interface WorkerNavigator {};  
    2.  WorkerNavigator implements NavigatorID;  
    3.  WorkerNavigator implements NavigatorOnLine; 

其中,有一點需要注意:如果接口的相對命名空間對象為 Window 對象的時候,WorkerNavigator 對象一定不可以存在,即無法再使用這個對象。

創建與終止線程

在講解創建新的工作線程之前,我們先看下 W3C 規范對工作線程的定義。工作線程規范中定義了線程的抽象接口類 AbstractWorker ,專用線程以及共享線程都繼承自該抽象接口。專用線程以及共享線程的創建方法讀者可以參考第一小節中的示例代碼。下面是此抽象接口的定義。

   1.AbstractWorker 抽象接口

  • 清單 8. AbstractWorker 抽象接口代碼

       此外,該接口還定義了錯誤處理的事件處理器 onerror,當工作線程在通信過程中遇到錯誤時便會觸發這個事件處理器。

   2.專用線程及其定義

  • 清單 9. 專用線程定義代碼
    1. [Constructor(in DOMString scriptURL)]  
    2.  interface Worker : AbstractWorker {  
    3.   void terminate();  
    4.  
    5.   void postMessage(in any message, in optional MessagePortArray ports);  
    6.            attribute Function onmessage;  
    7.  };  

        當創建完線程以后,我們可以調用 terminate() 方法去終止一個線程。每個專用線程都擁有一個隱式的 MessagePort 對象與之相關聯。這個端口隨著線程的創建而被創建出來,但并沒有暴露給用戶。所有的基于這個端口的消息接收都以線程本身為目標。

    3.共享線程及其定義

  • 清單 10. 共享線程定義代碼   
    1. [Constructor(DOMString scriptURL, optional DOMString name)]  
    2. interface SharedWorker : AbstractWorker {  
    3. readonly attribute MessagePort port;  
    4. };  

共享線程同專用線程一樣,當創建完線程以后,我們可以調用 terminate() 方法去終止一個共享線程。

#p#

工作線程位置屬性

工作線程被創建出來以后,需要記錄它的狀態以及位置信息,在工作線程規范中定義了 WorkerLocation 來表示它們的位置。接口定義如下:

  • 清單 11. 共享線程定義代碼
    1. interface WorkerLocation {  
    2.   // URL decomposition IDL attributes  
    3.   stringifier readonly attribute DOMString href;  
    4.   readonly attribute DOMString protocol;  
    5.   readonly attribute DOMString host;  
    6.   readonly attribute DOMString hostname;  
    7.   readonly attribute DOMString port;  
    8.   readonly attribute DOMString pathname;  
    9.   readonly attribute DOMString search;  
    10.   readonly attribute DOMString hash;  
    11.  };  

WorkerLocation 對象表示了工作線程腳本資源的絕對 URL 信息。我們可以使用它的 href 屬性取得這個對象的絕對 URL。WorkerLocation 接口還定義了與位置信息有關的其它屬性,例如:用于信息傳輸的協議(protocol),主機名稱(hostname),端口(port),路徑名稱(pathname)等。

工作線程(Web Worker)應用與實踐

我們可以寫出很多的例子來說明后臺工作線程的合適的用法,下面我們以幾種典型的應用場景為例,用代碼實例的形式講解在各種需求背景下正確的使用它們。

應用場景一:使用工作線程做后臺數值(算法)計算

工作線程最簡單的應用就是用來做后臺計算,而這種計算并不會中斷前臺用戶的操作。下面我們提供了一個工作線程的代碼片段,用來執行一個相對來說比較復雜的任務:計算兩個非常大的數字的最小公倍數和最大公約數。

在這個例子中,我們在主頁面中創建一個后臺工作線程,并且向這個工作線程分配任務(即傳遞兩個特別大的數字),當工作線程執行完這個任務時,便向主頁面程序返回計算結果,而在這個過程中,主頁面不需要等待這個耗時的操作,可以繼續進行其它的行為或任務。

我們把這個應用場景分為兩個主要部分,一個是主頁面,可以包含主 JavaScript 應用入口,用戶其它操作 UI 等。另外一個是后臺工作線程腳本,即用來執行計算任務。代碼片段如下:

  • 清單 12. 主程序頁面代碼
  1. <!DOCTYPE HTML>  
  2.  <html>  
  3.  <head>  
  4.  <title>  
  5.  Background Worker Application Example 1: Complicated Number Computation  
  6.  </title>  
  7.  </head>  
  8.  <body>  
  9.  <div>  
  10.  The least common multiple and greatest common divisor is:  
  11.  <p id="computation_results">please wait, computing … </p>  
  12.  </div>  
  13.   <script>  
  14.    var worker = new Worker('numberworker.js');  
  15.  worker.postMessage("{first:347734080,second:3423744400}");  
  16.    worker.onmessage = function (event)  
  17.  {  
  18.   document.getElementById(' computation_result').textContent = event.data;  
  19.  };  
  20.   </script>  
  21.  </body>  
  22.  </html>  
  • 清單 13. 后臺工作線程代碼
    1. /**   
    2.  * This worker is used to calculate   
    3.  * the least common multiple   
    4.  * and the greatest common divisor   
    5.  */   
    6.   
    7. onmessage = function (event)   {   
    8.  var first=event.data.first;    
    9. var second=event.data.second;    
    10. calculate(first,second);   };      
    11. /*   * calculate the least common multiple   * and the greatest common divisor   */    
    12. function calculate(first,second) {       
    13. //do the calculation work    
    14. var common_divisor=divisor(first,second);    
    15. var common_multiple=multiple(first,second);      
    16.  postMessage("Work done! " +  "The least common multiple is "+common_divisor   +" and the greatest common divisor is "+common_multiple);   }      
    17.  /**   * calculate the greatest common divisor   * @param number   * @param number   * @return   */    
    18. function divisor(a, b) {    
    19. if (a % b == 0) {   return b;   }  
    20. else {   return divisor(b, a % b);   }   }     
    21. /**   * calculate the least common multiple   * @param number   * @param number   * @return   */    
    22. function multiple( a,  b) {   var multiple = 0;   multiple = a * b / divisor(a, b);   return multiple;   }    

在主程序頁面中,我們使用 Worker()構造函數創建一個新的工作線程,它會返回一個代表此線程本身的線程對象。接下來我們使用這個線程對象與后臺腳本進行通信。線程對象有兩個主要事件處理器:postMessage 和 onmessage 。postMessage 用來向后臺腳本發送消息,onmessage 用以接收從后臺腳本中傳遞過來的消息。

在后臺工作線程代碼片段中,我們定一個兩個 JavaScript 函數,一個是 function divisor:用以計算最大公約數,一個是 function multiple:用以計算最小公倍數。同時工作線程的 onmessage 事件處理器用以接收從主頁面中傳遞過來的數值,然后把這兩個數值傳遞到 function calculate 用以計算。當計算完成后,調用事件處理器 postMessage,把計算結果發送到主頁面。

應用場景二:使用共享線程處理多用戶并發連接

由于線程的構建以及銷毀都要消耗很多的系統性能,例如 CPU 的處理器調度,內存的占用回收等,在一般的編程語言中都會有線程池的概念,線程池是一種對多線程并發處理的形式,在處理過程中系統將所有的任務添加到一個任務隊列,然后在構建好線程池以后自動啟動這些任務。處理完任務后再把線程收回到線程池中,用于下一次任務調用。線程池也是共享線程的一種應用。

在 HTML5 中也引入了共享線程技術,但是由于每個共享線程可以有多個連接,HTML5 對共享線程提供了和普通工作線程稍微有些區別的 API 接口。下面我們提供幾個例子來講述對共享線程的用法。

下面我們給出一個例子:創建一個共享線程用于接收從不同連接發送過來的指令,然后實現自己的指令處理邏輯,指令處理完成后將結果返回到各個不同的連接用戶。

 

  • 清單 14. 共享線程用戶連接頁面代碼
    1. <!DOCTYPE html>  
    2. <html>   
    3. <head>   <meta charset="UTF-8">   
    4. <title>Shared worker example: how to use shared worker in HTML5</title>    
    5. <script>    var worker = new SharedWorker('sharedworker.js');    
    6. var log = document.getElementById('response_from_worker');   
    7. worker.port.addEventListener('message', function(e) {   
    8. //log the response data in web page   log.textContent =e.data;    }, false);   
    9.  worker.port.start();    worker.port.postMessage('ping from user web page..');      
    10.  //following method will send user input to sharedworker    
    11. function postMessageToSharedWorker(input)    {    
    12. //define a json object to construct the request    
    13. var instructions={instruction:input.value};   
    14.  worker.port.postMessage(instructions);    }  </script>   
    15. </head>  
    16. <body onload=''>   
    17. <output id='response_from_worker'>  
    18.  Shared worker example: how to use shared worker in HTML5   </output>  
    19.  send instructions to shared worker:  
    20. <input type="text" autofocus oninput="postMessageToSharedWorker(this);return false;">   
    21. </input>  
    22. </body>  
    23. </html>  
  • 清單 15. 用于處理用戶指令的共享線程代碼
  1. // 創建一個共享線程用于接收從不同連接發送過來的指令,指令處理完成后將結果返回到各個不同的連接用戶。 
  2.  
  3.  /*  
  4.  * define a connect count to trace connecting  
  5.  * this variable will be shared within all connections  
  6.  */  
  7.  
  8. var connect_number = 0;   onconnect = function(e) {   
  9. connect_numberconnect_numberconnect_number =connect_number+ 1;   
  10. //get the first port here   var port = e.ports[0];   
  11. port.postMessage('A new connection! The current connection number is '   + connect_number);   port.onmessage = function(e) { 
  12.  //get instructions from requester  
  13. var instruction=e.data.instruction;  
  14. var results=execute_instruction(instruction);   
  15.   port.postMessage('Request: '+instruction+' Response '+results     +' from shared worker...');  
  16.  };  
  17. };  
  18.  /*  * this function will be used to execute the instructions send from requester  * @param instruction  * @return  */  
  19. function execute_instruction(instruction)  {  
  20. var result_value;  
  21. //implement your logic here  //execute the instruction...  
  22. return result_value  }   

#p#

  • 清單 16. 主頁面(僅僅是用來顯示計算結果)代碼
  1. <!DOCTYPE html>  
  2. <html>  
  3. <head>   
  4. <meta charset="UTF-8">   
  5. <title>Shared worker example: how to use delegation worker in HTML5</title>   
  6. <script>   
  7.  var worker = new SharedWorker('delegationworker.js');   
  8.  var log = document.getElementById('response_from_worker');   
  9.  worker.onmessage = function (event) {    
  10. //resolve the population from delegation worker    
  11. var resultdata=event.data;    
  12. var population=resultdata.total_population;    
  13. var showtext='The total population of the word is '+population;    
  14. document.getElementById('response_from_worker').textContent = showtext;    };  
  15.  </script>    
  16. </head>   
  17. <body onload=''>   
  18. <output id='response_from_worker'>   Shared worker example: how to use delegation worker in HTML5   </output>   
  19. </body>   
  20. </html>  
  • 清單 17. 主工作線程代碼
    1. /*  
    2.  * define the country list in the whole word  
    3.  * take following Array as an example  
    4.  */  
    5.  
    6. var country_list = ['Albania','Algeria','American','Andorra','Angola','Antigua','....'];   
    7.  // define the variable to record the population of the word   var total_population=0;  
    8.  var country_size=country_list.length;   var processing_size=country_list.length;    
    9. for (var i = 0; i < country_size; i++)   {   
    10. var worker = new Worker('subworker.js');    
    11. //wrap the command, send to delegations   
    12.  var command={command:'start',country:country_list[i]};    
    13. worker.postMessage(command);    worker.onmessage = update_results;   }    
    14. /*   * this function will be used to update the result   * @param event   * @return   */    
    15. function storeResult(event)   {   
    16. total_population += event.data;  
    17.  processing_size -1;   
    18. if (processing_size <= 0)   
    19. {   //complete the whole work, post results to web page  
    20.  postMessage(total_population);   }   }  
  • 清單 18. 代理線程代碼
  1. //define the onmessage hander for the delegation  
  2.  
  3.  
  4. onmessage = start_calculate;   
  5.  /*  
  6.  * resolve the command and kick off the calculation  
  7.  */  
  8.   
  9.  
  10. function start_calculate(event)   {   
  11. var command=event.data.command;   
  12. if(command!=null&&command=='start')   {   
  13. var coutry=event.data.country;  
  14. do_calculate(country);   }   
  15. onmessage = null;   }   
  16.  /*  
  17.  * the complex calculation method defined here  
  18.  * return the population of the country  
  19.  */  
  20.   
  21. function do_calculate(country)   {    
  22. var population = 0;    
  23. var cities=//get all the cities for this country    
  24. for (var i = 0; i < cities.length; i++){    
  25. var city_popu=0;        
  26. // perform the calculation for this city    
  27. //update the city_popu    
  28. population += city_popu;    }   
  29.   postMessage(population);    
  30. close();   }   

總結

HTML5 Web Worker 的多線程特性為基于 Web 系統開發的程序人員提供了強大的并發程序設計功能,它允許開發人員設計開發出性能和交互更好的富客戶端應用程序。本文不僅僅詳細講述 HTML5 中的多線程規范。同時,也以幾種典型的應用場景為例,以實例的形式講解 HTML5 中多線程編程以及應用,為用戶提供了詳細而全面的參考價值,并且指導開發人員設計和構建更為高效和穩定的 Web 多線程應用。

原文鏈接:http://www.ibm.com/developerworks/cn/web/1112_sunch_webworker/index.html

 

責任編輯:陳四芳 來源: developerWorks中國
相關推薦

2024-05-17 12:56:09

C#編程線程

2011-02-23 14:57:41

webweb開發HTML

2009-02-24 08:36:51

多線程線程池網絡服務器

2012-02-23 10:28:43

AppCanHTML5移動應用

2023-06-16 08:36:25

多線程編程數據競爭

2024-01-09 08:28:44

應用多線程技術

2013-03-22 08:59:57

HTML5移動應用Web App

2014-03-20 10:50:44

HTML5 定位技術

2011-05-11 12:59:18

HTML5

2013-07-16 10:12:14

iOS多線程多線程概念多線程入門

2012-08-30 16:24:04

HTML5歐朋W3C

2012-06-20 15:21:11

HTML5Opera歐朋瀏覽器

2012-06-27 17:17:55

HTML5

2013-08-08 10:00:01

Amazon AppsHTML5

2011-11-28 13:15:25

HTML5移動應用

2023-06-13 13:39:00

多線程異步編程

2009-03-12 10:52:43

Java線程多線程

2015-06-10 10:18:27

WebAPP開發技巧

2012-03-29 09:18:47

HTML5WEB

2013-01-24 10:26:04

HTML5HTML 5HTML5的未來
點贊
收藏

51CTO技術棧公眾號

在线播放日韩av| 欧美色图在线视频| 91久久精品在线| 久久精品波多野结衣| 麻豆成人入口| 欧美色图第一页| 8x8ⅹ国产精品一区二区二区| 蜜臀av免费在线观看| 新67194成人永久网站| 在线观看久久久久久| 亚洲丝袜在线观看| 竹内纱里奈兽皇系列在线观看 | 亚洲激情校园春色| 精品久久sese| 99riav国产| 久久精品一区二区国产| 欧美成年人视频| 日韩乱码人妻无码中文字幕久久| 亚洲人体在线| 在线一区av| 天堂精品在线视频| 欧美日韩亚洲天堂| av中文字幕av| 第一视频专区在线| 粉嫩久久99精品久久久久久夜| 日本一区二区三区四区视频| 欧美又粗又大又长| 欧美一站二站| 精品国产乱码久久久久久浪潮| 一本久道综合色婷婷五月| 午夜激情在线| 1024亚洲合集| 日本在线观看一区| 人妻少妇精品无码专区久久| 国模一区二区三区白浆| 国产99在线|中文| 国产精品a成v人在线播放| 99久精品视频在线观看视频| 国产午夜精品全部视频在线播放| 日本50路肥熟bbw| 亚洲综合资源| 欧美视频中文一区二区三区在线观看| 波多野结衣家庭教师在线| 九色porny在线| 国产精品免费视频网站| 欧美xxxx黑人又粗又长密月| 西西人体44www大胆无码| 国产精品一区二区黑丝| 91在线网站视频| 中文字幕一区二区人妻痴汉电车| 蜜桃视频一区| 青青久久aⅴ北条麻妃| 日本在线观看视频网站| 欧美日韩一区自拍| 欧美激情一区二区三级高清视频| 在线观看成人毛片| 欧美fxxxxxx另类| 亚洲电影中文字幕| 粉嫩虎白女毛片人体| 涩涩视频在线播放| 欧美性69xxxx肥| 黄色国产精品视频| 伊人久久综合一区二区| 高跟丝袜一区二区三区| 国产aaa一级片| 亚洲精品**中文毛片| 日韩欧美中文字幕在线播放| 国产又大又硬又粗| 欧美国产大片| 欧美日韩国产片| 国产三级精品三级在线| 国语精品视频| 亚洲国产精品久久| 青青草视频播放| 久久av影视| 国产亚洲精品综合一区91| 国产一级久久久久毛片精品| 久久中文视频| 欧美成人在线网站| 国产精品二区一区二区aⅴ| 91久久黄色| 欧洲一区二区视频| 国产情侣呻吟对白高潮| 蜜臀a∨国产成人精品| 国产在线观看精品| 国产av无码专区亚洲av麻豆| 不卡区在线中文字幕| 欧美一区少妇| 国产精品久久久久久福利| 艳妇臀荡乳欲伦亚洲一区| 俄罗斯av网站| 美女视频一区| 亚洲精品99久久久久中文字幕| 51妺嘿嘿午夜福利| 欧美国产专区| 全球成人中文在线| 国产精品色综合| av一区二区三区| 神马一区二区影院| 成年网站在线视频网站| 日本韩国欧美一区| 亚洲av无一区二区三区久久| 国产成人ay| 久久精品一本久久99精品| 在线观看 中文字幕| 麻豆精品一区二区av白丝在线| 99精彩视频在线观看免费| 韩国中文免费在线视频| 一区二区三区蜜桃网| 免费黄色福利视频| 视频在线亚洲| 中文字幕免费国产精品| 日韩欧美视频在线免费观看| 久久精品久久综合| 久久资源亚洲| 久久免费电影| 91精品国产手机| 97人妻精品一区二区免费| 成人春色在线观看免费网站| 色偷偷91综合久久噜噜| 国产超碰人人爽人人做人人爱| av网站导航在线观看免费| 狠狠久久伊人| 亚洲欧美激情另类校园| 免看一级a毛片一片成人不卡| 日本不卡一区二区| 精品网站在线看| 思思99re6国产在线播放| 狠狠久久五月精品中文字幕| 日本少妇xxx| 1024精品久久久久久久久| 日韩美女在线看| 少妇一区二区三区四区| 一区二区三区精品视频| av在线免费看片| 欧美精品乱码| 国产成人精品视频在线| 欧美日韩国产综合视频| 亚州成人在线电影| 男女性杂交内射妇女bbwxz| 艳女tv在线观看国产一区| 国产精品丝袜久久久久久高清 | 欧美成人乱码一区二区三区| 激情五月激情综合| 男男视频亚洲欧美| 天堂一区二区三区 | 亚洲一区二区日韩| 国产精品一区久久| melody高清在线观看| 色欧美片视频在线观看| 在线观看福利片| 久久九九国产| 神马影院我不卡| 99re久久| 精品国产一区二区在线| 91麻豆国产在线| 中文字幕视频一区二区三区久| 一区二区三区免费播放| 日韩av免费大片| 国产区精品视频| 米奇777四色精品人人爽| 欧美高清视频一二三区| 澳门黄色一级片| 国产传媒一区在线| 日韩成人手机在线| 国产一区福利| 欧美最顶级的aⅴ艳星| 日韩三级电影网| 91成人网在线| 熟女av一区二区| 国产成人午夜视频| 免费观看国产精品视频| 一道本一区二区三区| 国产成人精品优优av| 国产精品四虎| 91精品国产乱| 日韩特黄一级片| 中文字幕av一区二区三区高 | 国产福利一区二区三区视频在线 | 超碰在线最新| 亚洲第一天堂无码专区| 青草视频在线观看免费| 欧美国产日韩在线观看| 久久久久久久久久毛片| 一区二区亚洲精品| 日本不卡在线观看| 精品中文视频| 91超碰caoporn97人人| 成人高清免费观看mv| 91精品国产一区二区三区蜜臀 | 一本大道久久精品懂色aⅴ| 九一在线免费观看| 成人深夜福利app| www.欧美日本| 欧美三区在线| 日韩欧美精品一区二区三区经典| 精品一区二区三区亚洲| 日本欧美精品在线| 天堂va在线| 亚洲午夜精品久久久久久性色| 国产suv一区二区| 色网站国产精品| 麻豆亚洲av熟女国产一区二| 国产日韩精品视频一区| 国产黑丝在线视频| 久久蜜桃精品| 国产午夜精品视频一区二区三区| 男男gay无套免费视频欧美| 91精品中国老女人| 成人香蕉视频| 欧美精品制服第一页| 国产精品麻豆一区二区三区| 亚洲国产欧美一区二区三区久久| 一级黄色片在线看| 狠狠躁夜夜躁人人躁婷婷91| 欧美精品99久久久| 国产精品免费av| 精品国产av无码| 成人av网站在线| 欧美在线a视频| 青青草一区二区三区| 日本www在线视频| 激情视频一区二区三区| 一区精品在线| 日韩中字在线| 日本在线播放一区| 亚洲人成网www| 国产日韩欧美综合精品| 精品国产伦一区二区三区观看说明 | 亚洲精品成人无码熟妇在线| 国产成人免费视频精品含羞草妖精| 五月婷婷深爱五月| 亚洲一区二区网站| a级黄色小视频| 综合久久婷婷| 秋霞在线一区二区| 国产韩日影视精品| 一本一道久久a久久综合精品| 国产欧美一区二区精品久久久| 国产伦精品一区二区三区视频孕妇 | 欧美xxxx黑人又粗又长密月| 韩国女主播一区二区三区| 99国产视频| 99香蕉久久| 韩国成人av| 欧美美女黄色| 久久久久久久久久码影片| 欧美三级电影在线| 久久久久久久久一区| 亚洲视频分类| 欧美人xxxxx| jizzjizz欧美69巨大| 日本一区二区三区视频在线观看| 国产精品一区二区三区av麻| 五月天久久狠狠| 久久亚洲成人| 老司机av福利| 国产一区二区三区四区老人| 青青青在线观看视频| 亚洲美女黄色| 日韩少妇内射免费播放18禁裸乳| 蘑菇福利视频一区播放| 精品免费国产一区二区| 日韩电影免费在线| 亚洲美女爱爱视频| 国产精品亚洲一区二区三区妖精| 绯色av蜜臀vs少妇| 99久久亚洲一区二区三区青草| 久久一区二区电影| 国产日韩欧美电影| 99re6热在线精品视频| 综合久久给合久久狠狠狠97色 | 国产精品老女人精品视频| 99久久久国产精品免费调教网站| 国产美女精彩久久| 日韩精品一区二区三区中文在线 | 亚洲色图制服丝袜| 欧美人与禽zozzo禽性配| 亚洲成人免费视频| 国产女主播喷水视频在线观看| 欧美绝品在线观看成人午夜影视| 亚洲AV午夜精品| 亚洲人成电影在线| 黄网站app在线观看| 欧美极品少妇xxxxⅹ免费视频| 在线天堂中文资源最新版| 国产精品一区专区欧美日韩| 国产精品高潮呻吟久久久久| 日韩免费av一区二区三区| 亚洲成av人片乱码色午夜| 欧美午夜性视频| 日本不卡一区二区三区高清视频| 欧美性猛交乱大交| 久久久噜噜噜久久中文字幕色伊伊| 欧美性生交大片| 天天av天天翘天天综合网色鬼国产| 波多野结衣一本一道| 日韩一区二区视频在线观看| 青春有你2免费观看完整版在线播放高清| 日韩亚洲欧美成人| 黄视频网站在线观看| 国产日韩精品在线播放| 奇米777国产一区国产二区| 在线一区高清| 亚洲欧美日韩视频二区| 天天做天天干天天操| 久久综合色8888| 久久久久成人片免费观看蜜芽| 91国偷自产一区二区三区观看 | 日本美女久久| 国产美女精品久久久| 91视频综合| 午夜精品久久久内射近拍高清| 国产精品亚洲一区二区三区妖精| 亚洲黄色免费视频| 亚洲国产精品久久久久婷婷884| 中文字幕在线播放av| 精品亚洲夜色av98在线观看| 日本高清在线观看视频| 国产精品免费视频久久久| 日韩成人一级| www.射射射| 国产精品影视网| 我要看黄色一级片| 欧洲在线/亚洲| 日韩av免费观影| 午夜精品蜜臀一区二区三区免费| 欧美日韩国产一区二区在线观看| 亚洲欧美影院| 日韩成人免费看| 加勒比一区二区| 高跟丝袜欧美一区| 无码精品人妻一区二区| 久久99精品国产99久久6尤物 | 欧美日韩中字一区| 国产视频精选在线| 日本精品一区二区三区在线| 日本国产精品| 人妻少妇精品无码专区二区| 国产成人免费视频一区| 99热精品免费| 日韩欧美一级二级三级久久久| 黄网站免费在线观看| 国产日韩在线免费| 日韩在线欧美| 8x8x成人免费视频| 亚洲欧美综合在线精品| 又骚又黄的视频| 综合久久五月天| 玖玖精品在线| youjizz.com亚洲| 国产在线精品一区二区不卡了 | 久久要要av| www.com久久久| 亚洲黄色性网站| 免费看日韩av| 91高清在线免费观看| 首页亚洲中字| 欧美精品成人网| 国产精品久久久久久久久免费相片| 中文字幕免费播放| 日韩视频在线观看免费| 国模大尺度视频一区二区| 日本天堂免费a| 99精品久久99久久久久| 久久久久女人精品毛片九一| 亚洲欧美在线播放| 成人国产精品入口免费视频| 在线综合视频网站| 粉嫩在线一区二区三区视频| 成年人免费看毛片| 亚洲四色影视在线观看| 成人精品视频在线观看| 久久这里只有精品8| 26uuu国产一区二区三区| 成人免费一级片| 久久91超碰青草是什么| 老牛影视av一区二区在线观看| 国产精品wwwww| 最近日韩中文字幕| 男人天堂av网| 国产精品高精视频免费| 91精品99| 中文字幕一区二区久久人妻网站| 欧美伊人久久久久久午夜久久久久| 日本三级视频在线播放| 国产高清在线一区| 丝袜美腿一区二区三区| 卡通动漫亚洲综合| 亚洲精品日韩在线| 祥仔av免费一区二区三区四区| 久久亚洲精品无码va白人极品| 久久久久久久久99精品| 国产手机视频在线| 国产99在线|中文| 欧美日韩亚洲三区| 在线观看日本中文字幕| 日韩一本二本av| 香蕉成人av| a天堂资源在线观看|