JavaScript多线程之二~~Node.js中的Web Worker
2015-12-24 13:09
183 查看
上次研究了Web Worker在浏览器中的现状和使用方法,顺便感慨这么好用的东西为啥Node.js中没有呢,没过几天就发现原来国外早在2011年11月的时候就有人在github上开源了Web Worker规范在Node.js上的实现。这个模块是基于node-threads-a-gogo模块(简称TAGG)做的,TAGG是个挺不错的模块,可以让Node.js实现多线程编程,充分使用服务器的资源。Node.js从此不再限于I/O密集型的场景,也使它的触角可以拓展到更加广阔的领域。相比于TAGG,webworker-threads(目前版本是0.6.2)提供了更加易用的功能,重要的是它的接口实现是参考HTML5中定义的Web Worker标准,易于掌握前后端一致的开发方法。
先看一张关于这个模块使用后整个Node.js系统的图示,点击查看出处:
参考webworker-threads的说明文档中的例子:
这段代码是让Node.js主线程建立一个工作线程,并且通过
从这段代码可以看出,Node.js中也可以通过webworker-threads模块,让编码者参考HTML5中的Web Worker规范来实现多线程编程应用。主线程和工作线程通过postMessage和onmessage发送和监听消息,使用方式非常简便。
为了证明Web Worker的运行和主线程确实是个异步的过程,可以通过CPU密集型的计算来检验:
上面的代码中,在Node.js的主线程建立了一个HTTP服务器,监听3333端口,当接受到客户端请求后,服务器端打印“====computing started===”并开始计算斐波那契数列40个值的和,这个计算工作在另外的线程中进行,主线程持续打印“主线程在运行”的字符串,斐波那契数列计算完成后主线程接受到计算结果并打印“====computing end===”字符串。运行结果如下:
从运算结果可以看出,当工作线程运算时,主线程并没有被阻塞。
由于webworker-threads是在TAGG的基础上实现的,因此也可以不使用Web Worker,而直接创建线程对象Thread或线程池ThreadPool来实现多线程编程。
API附录:
模块API:
引入webworker-threads的方式:
Web Worker API:
使用三种方式生成Web Worker对象:
Thread API:
创建方式:
Thread Pool API:
创建方式:
Web Worker内部全局属性和方法:
Thread全局属性和方法:
其他全局方法:
在每个worker中都可以使用下列方法协助调试:
更多的例子和API可以看参考文献。
参考文献:
1. webworker-threads
2. node-threads-a-gogo的GitHub链接
3. webworker-threads的GitHub链接
4. nodejs多线程,真正的非阻塞
5. Web Workers in HTML5
先看一张关于这个模块使用后整个Node.js系统的图示,点击查看出处:
参考webworker-threads的说明文档中的例子:
[code]var Worker = require('webworker-threads').Worker; // var w = new Worker('worker.js'); // Standard API // You may also pass in a function: var worker = new Worker(function(){ postMessage("I'm working before postMessage('ali')."); this.onmessage = function(event) { postMessage('Hi ' + event.data); self.close(); }; }); worker.onmessage = function(event) { console.log("Worker said : " + event.data); }; worker.postMessage('ali');
这段代码是让Node.js主线程建立一个工作线程,并且通过
worker.postMessage('ali');向工作线程发出消息,工作线程接受到消息后加上”Hi “后返回给主线程。运行结果如下:
[code]Worker said : I'm working before postMessage('ali'). Worker said : Hi ali
从这段代码可以看出,Node.js中也可以通过webworker-threads模块,让编码者参考HTML5中的Web Worker规范来实现多线程编程应用。主线程和工作线程通过postMessage和onmessage发送和监听消息,使用方式非常简便。
为了证明Web Worker的运行和主线程确实是个异步的过程,可以通过CPU密集型的计算来检验:
[code]var Worker = require('webworker-threads').Worker; require('http').createServer(function(req, res) { var fibo = new Worker(function() { function fibo(n) { return n > 1 ? fibo(n - 1) + fibo(n - 2) : 1; } this.onmessage = function(event) { postMessage(fibo(event.data)); } }); fibo.onmessage = function(event) { console.log('====computing end==='); res.end('fib(40) = ' + event.data); }; fibo.postMessage(40); console.log('====computing started==='); interval(); }).listen(3333); console.log("server started"); function interval(){ setInterval(function(){ console.log("主线程在运行"); },100); }
上面的代码中,在Node.js的主线程建立了一个HTTP服务器,监听3333端口,当接受到客户端请求后,服务器端打印“====computing started===”并开始计算斐波那契数列40个值的和,这个计算工作在另外的线程中进行,主线程持续打印“主线程在运行”的字符串,斐波那契数列计算完成后主线程接受到计算结果并打印“====computing end===”字符串。运行结果如下:
[code]server started ====computing started=== 主线程在运行 主线程在运行 主线程在运行 主线程在运行 主线程在运行 主线程在运行 主线程在运行 主线程在运行 主线程在运行 主线程在运行 主线程在运行 主线程在运行 主线程在运行 主线程在运行 主线程在运行 ====computing end=== 主线程在运行 主线程在运行 主线程在运行 主线程在运行 ....
从运算结果可以看出,当工作线程运算时,主线程并没有被阻塞。
由于webworker-threads是在TAGG的基础上实现的,因此也可以不使用Web Worker,而直接创建线程对象Thread或线程池ThreadPool来实现多线程编程。
API附录:
模块API:
引入webworker-threads的方式:
var Threads= require('webworker-threads');
Threads.Worker()返回Worker对象
Threads.create()返回thread对象
Threads.createPool(numThreads)返回threadPool对象
Web Worker API:
使用三种方式生成Web Worker对象:
[code]var worker= new Threads.Worker('worker.js'); var worker= new Threads.Worker(function(){ ... }); var worker= new Threads.Worker();
worker.postMessage(data)向worker发送消息
worker.onmessage从worker接受消息
worker.terminate()结束worker线程
worker.addEventListener(type,callback)通常用于
worker.addEventListener('message', callback)
dispatchEvent(event)未实现
removeEventListener(type)未实现
worker.thread返回worker的thread对象
Thread API:
创建方式:
var thread= Threads.create();
thread.id线程序列号
thread.load(absolutePath[,callback])读取绝对路径上的文件并执行文件内容和callback回调函数
thread.eval(program[,callback])在thread全局上下文中执行program代码,之后调用callback(error,completionValue)
thread.on(eventType,listener)注册事件监听
thread.once(eventType,listener)注册单次事件监听
thread.removeAllListeners([eventType])移除事件监听
thread.emit(eventType,eventData[,eventData……])发出eventType类型的事件
thread.destroy()摧毁thread对象
Thread Pool API:
创建方式:
var threadPool=Threads.createPool(numberOfThreads);
threadPool.load(absolutePath[,callback])在所有池内线程上执行
thread.load(absolutePath[,callback])
threadPool.any.eval(program,callback)在任意池内线程执行
thread.eval()
threadPool.any.emit(eventType,eventData[,eventData...])在任意池内线程执行
thread.emit()
threaPool.all.eval(program,callback)在所有池内线程上执行
thread.eval()
threadPool.all.emit(eventType,eventData[,eventData...])在所有池内线程执行
thread.emit()
threadPool.on(eventType,listener)在任意池内线程注册事件监听
threadPool.totalThread()返回池内线程数目
threadPool.idleThread()返回池内空闲线程数目
threadPool.pendingJobs()返回尚未执行的工作数目
threadPool.destroy([rudely])摧毁线程池,鉴于rudely等待pendingJobs数量为0时摧毁还是立刻摧毁
Web Worker内部全局属性和方法:
self.postMessage(data)向主线程发送消息
self.onmessage定义接受主线程消息的回调函数
self.close()关闭自身线程
self.addEventListener(type,callback)定义事件监听
self.dispatchListener(event)发出事件
self.removeEventListener(type)未实现
self.importScripts(file[,file,...])从磁盘加载js文件并在当前线程上下文中执行
self.thread返回webworker的线程对象
Thread全局属性和方法:
self.id线程序列号
self.on(eventType,listener)类似于
thread.on()
self.once(eventType,listener)类似于
thread.once()
self.emit(eventType,eventData[,eventData...])类似于
thread.emit()
self.removeAllListener([eventType])类似于
thread.removeAllListeners()
self.nextTick(function)类似于
process.nextTick(),但是比它更快
其他全局方法:
在每个worker中都可以使用下列方法协助调试:
console.log(arg1[,arg2...])
console.err(arg1[,arg2...])打印到stderr
puts(arg1[,arg2...])打印到stdout
更多的例子和API可以看参考文献。
参考文献:
1. webworker-threads
2. node-threads-a-gogo的GitHub链接
3. webworker-threads的GitHub链接
4. nodejs多线程,真正的非阻塞
5. Web Workers in HTML5
相关文章推荐
- ubuntu server 14.04 下 pomelo 环境配置
- nodejs如何利用rpc调用python
- lib-qqwry v1.0 发布 nodejs解析纯真IP库(qqwry.dat)
- 1. webstorm配置nodeJs环境
- LeetCode Swap Nodes in Pairs
- nodejs npm常用命令
- nodejs eventEmitter源码解读
- Hadoop 格式化namenode错误:FATAL namenode.NameNode: Exception innamenode join
- ubuntu -- 安装最新版的nodejs
- Nodejs源码解析之Buffer
- Node.js + Web Socket 打造即时聊天程序嗨聊
- 提升 Node.js 应用性能的 5 个技巧
- Node.js开发者必须了解的4个JS要点
- 使用keymetrics实时监控Node.js程序
- nodeJs--模块module.exports与实例化方法;
- Nodejs异步流程控制Async
- nodejs 事件驱动
- Node.js回调黑洞全解:Async、Promise 和 Generator
- Trouble install node.js with homebrew
- 237. Delete Node in a Linked List