WebWorker(工作线程)笔记
来源:互联网 发布:如何评价林俊杰 知乎 编辑:程序博客网 时间:2024/05/22 12:33
WebWorker简介
- 产生原因:js是单线程,比如当js运行一段代码时,如果这段代码没有运行完成,是无法做其他的操作。随着HTML要处理的任务越来越重,单线程有时满足使用要求;
- 概念:Web Worker允许开发人员编写能长时间运行而不被用户中断的后台程序,去执行事务或者逻辑,并同时保证页面对用户的及时响应。简言之,即允许js创建多个线程,但子线程完全受主线程控制,而且子线程不能操作DOM;
- 特点:能够长时间运行(响应),理想的启动性能以及理想的内存消耗;
- 使用说明:
- 无法访问DOM;
- 无法访问全局变量或全局函数(只能访问当前js中的函数);
- 无法调用alert或者confirm等函数;
- 无法访问window、document之类的浏览器全局变量;
- 可以使用setTimeout、setInterval;
- 可以使用XMLHttpRequest对象来做Ajax通信。
- 通过new Work(url)来创建work对象,加载的js文件不能跨域;
- 如果使用了WebWorker,必须将html页面部署到服务器上;
WebWorker原理
传统的线程可解释为轻量级进程,它和进程一样有独立的执行控制,一般情况下由操作系统负责调度。在HTML5中的多线程是指允许web程序并发的执行js脚本,每个脚本执行流都称为一个线程,彼此间相互独立,并由浏览器中的js引擎负责管理
WorkerGlobalScope全局上下文
主页面html执行的全局上下文是window,而WebWorker执行的全局上下文是WorkerGlobalScope(不知道是啥),所以无法访问window对象,其属性与window中的属性类似;WorkerGlobalScope作用域下常见的属性如下
1. self:表示对WorkerGlobalScope对象本身的引用,专用线程中执行结果为DedicatedWorkerGlobalScope,共享线程中执行结果为SharedWorkerGlobalScope;
2. location:表示用于初始化这个工作线程的脚本资源的绝对 URL;
3. close:关闭当前线程,与terminate作用类似。步骤:删除这个工作线程事件队列中的所有任务,设置 WorkerGlobalScope 对象的 closing 状态为 true (这将阻止以后任何新的任务继续添加到事件队列中来);
4. importScripts:可以通过importScripts批量加载js文件;
5. XMLHttpRequest:通过该对象发送Ajax请求;
6. setTimeout/setInterval:用法与window中一样;
7. addEventListener(onmessage)/postMessage:addEventListener方法可以代替onmessage
共享线程(Shared Worker)和专用线程(Dedicated Worker)
区别:
1. 专用线程会使用隐式的 MessagePort 实例,MessagePort对象支持 HTML5 中多线程提供的所有功能。当专用线程被创建的时候,MessagePort 的端口消息队列便被主动启用;而共享线程必须显式使用。
2. 创建方法:专用线程只有URL一个参数;而共享线程创建是如果提供了第二个参数,那么这个参数将被用于作为这个共享线程的名称。
3. Woker对象和SharedWorker对象
//专用线程var worker=new Worker('worker.js');worker.onmessage=function(){};worker.postMessage('123');worker.postMessage(data,[data]);//如果data为ArrayBuffer数据时,需要在第二个参数中指定它以提高传输效率;//共享线程var worker=new SharedWorker('SharedWorker.js','myShareWorker');worker.port.addEventListener('message',function(e){});worker.port.start();//在SharedWorker中使用addEventListener时,必须用worker.port.start()来启动这个端口worker.port.postMessage('123');
WebWorker之常用API
worker线程从上到下同步运行它的代码,worker线程从上到下同步运行它的代码,如果worker注册了message事件处理程序,只要其有可能触发,worker就一直在内存中,不会退出,所以通信完毕后得手动在主线程中terminate或者子线程中close掉,但如果worker没有监听消息,那么当所有任务执行完毕(包括计数器)后,他就会退出。
子线程与主线程互相传递消息使用的方法
//var worker =new Worker('worker.js');//主线程传消息给子线程worker.postMessage(data1);//在worker.js文件中,子线程传消息给主线程postMessage(data2);
主线程中终止worker,此后无法再利用其进行消息传递。注意:一旦terminate后,无法重新启用,只能另外创建
//var worker =new Worker('worker.js');worker.terminate();
主线程、子线程接收消息。可以用addEventListener代替
//var worker =new Worker('worker.js');//主线程接收来自子线程的消息 worker.onmessage=function(e){ var data=e.data; //e为MessageEvent对象};//在worker.js文件中,子线程接收来自主线程的消息onmessage=function(e){ var data=e.data;};
//var worker =new Worker('worker.js');worker.onerror = function(e){ //打印出错消息 console.log(e.message); //中断与子线程的联系 worker.terminate();}
WebWorker优缺点:
优点:
1. 可以加载一个JS进行大量的复杂计算而不挂起主进程,并通过postMessage,onmessage进行通信
2. 可以在worker中通过importScripts(url)加载另外的脚本文件
3. 可以使用 setTimeout(), clearTimeout(), setInterval(), and clearInterval()
4. 可以使用XMLHttpRequest来发送请求
5. 可以访问navigator的部分属性
缺点:
1. 不能跨域加载JS(html主页面可以)
2. worker内代码不能访问DOM
3. 各个浏览器对Worker的实现不大一致,例如FF里允许worker中创建新的worker,而Chrome中就不行
WebWorker应用
/**创建一个共享线程用于接收从不同连接发送过来的指令,指令结果处理完成后将结果返回到各个不同的连接用户*///Html文件<!Doctype html><html> <head> <meta charset='utf-8' /> <title>Calculate Number</title> </head> <body> <div> The last common multiple and greateset common divisor is : <p id='result'>Please wait,computing......</p> </div><script type='text/javascript'> var worker=new Worker('js/webworker.js'); worker.onmessage=function(e){//主线程接收来自子线程的消息 document.getElementById('result').innerHTML=e.data; } worker.postMessage({first:100,second:50});//主线程向子线程发消息 worker.onerror=function(){ alert('线程出错!');//异常处理 }</script> </body></html>//webworker.js文件onmessage=function(e){ //子线程接收来自主线程的消息 var data=e.data; Calculate(data.first,data.second);}function Calculate(first,second){ var common_divisor=divisor(first,second); var common_multiple=multiple(first,second); postMessage("Work done! " +"The least common multiple is "+common_divisor +" and the greatest common divisor is "+common_multiple); //子线程向主线程发消息}function divisor(a, b) { if (a % b == 0) return b; else return divisor(b, a % b); } function multiple( a, b) { var multiple = 0; multiple = a * b / divisor(a, b); return multiple; }
由于线程的构建以及销毁都要消耗很多的系统性能,例如 CPU 的处理器调度,内存的占用回收等,在一般的编程语言中都会有线程池的概念,线程池是一种对多线程并发处理的形式,在处理过程中系统将所有的任务添加到一个任务队列,然后在构建好线程池以后自动启动这些任务。处理完任务后再把线程收回到线程池中,用于下一次任务调用。线程池也是共享线程的一种应用。 (Web2D中有专用线程实现线程池的用法,即创建4个专用线程)
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Shared worker example: how to use shared worker in HTML5</title> <script> var worker = new SharedWorker('sharedworker.js'); //创建线程 var log = document.getElementById('response_from_worker'); worker.port.addEventListener('message', function(e) { log.textContent =e.data; }, false); worker.port.start(); //启动端口 worker.port.postMessage('ping from user web page..'); //Send user input to sharedworker function postMessageToSharedWorker(input) { //Define a json object to construct the request var instructions={ instruction:input.value }; worker.port.postMessage(instructions); } </script></head> <body onload=''> <output id='response_from_worker'> How to use shared worker in HTML5!</output> Send instructions to shared worker: <input type="text" autofocus oninput="postMessageToSharedWorker(this);return false;"> </input> </body> </html> /* * define a connect count to trace connecting * this variable will be shared within all connections */ //sharedworker.js文件var connect_number = 0; //记录连接到这个共享线程的总onconnect = function(e) { connect_number =connect_number+ 1; //get the first port here var port = e.ports[0]; port.postMessage('A new connection! The current connection number is ' + connect_number); port.onmessage = function(e) { //get instructions from requester var instruction=e.data.instruction; var results=execute_instruction(instruction); port.postMessage('Request: '+instruction+' Response '+results +' from shared worker...'); }; }; /* * this function will be used to execute the instructions send from requester * @param instruction * @return */ function execute_instruction(instruction) { var result_value; //implement your logic here //execute the instruction... return result_value }
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Shared worker example: how to use delegation worker in HTML5</title> <script> var worker = new SharedWorker('delegationworker.js'); var log = document.getElementById('response_from_worker'); worker.onmessage = function (event) { //resolve the population from delegation worker var resultdata=event.data; var population=resultdata.total_population; var showtext='The total population of the word is '+population; document.getElementById('response_from_worker').textContent = showtext; }; </script></head> <body onload=''> <output id='response_from_worker'> Shared worker example: how to use delegation worker in HTML5 </output> </body> </html>/* * define the country list in the whole word * take following Array as an example */ var country_list = ['Albania','Algeria','American','Andorra','Angola','Antigua','....']; // define the variable to record the population of the word var total_population=0; var country_size=country_list.length; var processing_size=country_list.length; for (var i = 0; i < country_size; i++) { var worker = new Worker('subworker.js'); //wrap the command, send to delegations var command={command:'start',country:country_list[i]}; worker.postMessage(command); worker.onmessage = update_results; } /* * this function will be used to update the result * @param event * @return */ function storeResult(event) { total_population += event.data; processing_size -= 1; if (processing_size <= 0) { //complete the whole work, post results to web page postMessage(total_population); } }//define the onmessage hander for the delegation onmessage = start_calculate; /* * resolve the command and kick off the calculation */ function start_calculate(event) { var command=event.data.command; if(command!=null&&command=='start') { var coutry=event.data.country; do_calculate(country); } onmessage = null; } /* * the complex calculation method defined here * return the population of the country */ function do_calculate(country) { var population = 0; var cities=//get all the cities for this country for (var i = 0; i < cities.length; i++) { var city_popu=0; // perform the calculation for this city //update the city_popu population += city_popu; } postMessage(population); close(); }
- WebWorker(工作线程)笔记
- WebWorker 工作线程
- WebWorker
- webworker
- webWorker
- webWorker
- 线程池工作笔记
- webWorker操作
- webworker 探秘
- 浅谈webWorker
- 浅谈webWorker
- webWorker初识
- html5 多线程处理webWorker
- html5 webworker的应用
- 【面向HTML5--WebWorker】
- 工作队列 工作线程 工作(work_struct)
- UI线程和工作线程
- http://hi.baidu.com/webworker
- JDBC(4)—Preparedstatement
- 如何在jni中查看手机cpu构架
- Array.Add添加
- ubuntu主题
- Android避免多进程Application onCreate中初始化代码执行多次
- WebWorker(工作线程)笔记
- 【Eternallyc】HDU-2546-饭卡
- sklearn浅析(六)——Kernel Ridge Regression
- Myeclipse快捷键
- 拆箱与装箱
- 文章标题 HDU 3507 :Print Article (斜率dp优化)
- elasticsearch之Document APIs【Delete API】
- [学习笔记] 后缀自动机学习笔记
- XtraBackup工作原理