传统的线程可解释为轻量级进程,它和进程一样有独立的执行控制,一般情况下由操作系统负责调度。在HTML5中的多线程是指允许web程序并发的执行js脚本,每个脚本执行流都称为一个线程,彼此间相互独立,并由浏览器中的js引擎负责管理
主页面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
区别:
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');
worker线程从上到下同步运行它的代码,worker线程从上到下同步运行它的代码,如果worker注册了message事件处理程序,只要其有可能触发,worker就一直在内存中,不会退出,所以通信完毕后得手动在主线程中terminate或者子线程中close掉,但如果worker没有监听消息,那么当所有任务执行完毕(包括计数器)后,他就会退出。
//var worker =new Worker('worker.js');
//主线程传消息给子线程
worker.postMessage(data1);
//在worker.js文件中,子线程传消息给主线程
postMessage(data2);
//var worker =new Worker('worker.js');
worker.terminate();
//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();
}
优点:
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中就不行
/** 创建一个共享线程用于接收从不同连接发送过来的指令,指令结果处理完成后将结果返回到各个不同的连接用户 */
//Html文件
'utf-8' />
Calculate Number
The last common multiple and greateset common divisor is :
'result'>Please wait,computing......
//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;
}
"UTF-8">
Shared worker example: how to use shared worker in HTML5
''>
Send instructions to shared worker:
"text" autofocus οninput="postMessageToSharedWorker(this);return false;">
/* * 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
}
"UTF-8">
Shared worker example: how to use delegation worker in HTML5
''>
/* * 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();
}