JavaScript和线程
有什么方法可以在JavaScript中执行multithreading?
有关最新的支持信息,请参阅http://caniuse.com/#search=worker 。
以下是大约2009年的支持状态。
你想谷歌的话是JavaScript工作线程
除了Gears之外,现在还没有可用的东西,但是关于如何实现这个东西的讨论还是很多的,所以我想看这个问题,因为答案将来无疑会改变。
这是Gears: WorkerPool API的相关文档
WHATWG为工作者线程提供了一份build议草案: Web Workers
还有Mozilla的DOM工作线程
更新: 2009年6月,浏览器支持JavaScript线程的当前状态
Firefox 3.5有Web工作者。 networking工作者的一些演示,如果你想看到他们的行动:
- 模拟退火 (“Try it”链接)
- 太空侵略者 (链接在post的末尾)
- MoonBat JavaScript基准 (第一链接)
Gears插件也可以安装在Firefox中。
Safari 4和WebKit nightlies都有工作线程:
- JavaScript Ray Tracer
Chrome浏览器已经embedded了Gears,所以它可以执行线程,虽然它需要用户的确认提示(并且使用不同的API给web工作者,尽pipe它可以在任何安装了Gears插件的浏览器中运行):
- 谷歌齿轮WorkerPool演示 (不是一个很好的例子,因为它运行速度太快,无法在Chrome和Firefox中testing,尽pipeIE运行速度足以让它阻止交互)
IE8和IE9只能安装Gears插件
在JavaScript中使用multithreading和asynchronous的不同方式
在HTML5之前,JavaScript只允许每页执行一个线程。
用Yield , setTimeout()
, setInterval()
, XMLHttpRequest
或事件处理程序来模拟一个asynchronous的执行有一些奇怪的方法(有关yield和setTimeout()
的例子,请参阅本文结尾部分)。
但是使用HTML5,我们现在可以使用“工作线程”来并行执行function。 这是一个使用的例子。
真正的multithreading
multithreading:JavaScript工作线程
HTML5引入了Web Worker线程(请参阅: 浏览器兼容性 )
注意:IE9和更早版本不支持它。
这些工作线程是在后台运行的JavaScript线程,不会影响页面的性能。 有关Web Worker的更多信息,请阅读文档或本教程 。
这里有一个简单的例子,其中3个Web Worker线程计数到MAX_VALUE,并在页面中显示当前的计算值:
//As a worker normally take another JavaScript file to execute we convert the function in an URL: http://stackoverflow.com/a/16799132/2576706 function getScriptPath(foo){ return window.URL.createObjectURL(new Blob([foo.toString().match(/^\s*function\s*\(\s*\)\s*\{(([\s\S](?!\}$))*[\s\S])/)[1]],{type:'text/javascript'})); } var MAX_VALUE = 10000; /* * Here are the workers */ //Worker 1 var worker1 = new Worker(getScriptPath(function(){ self.addEventListener('message', function(e) { var value = 0; while(value <= e.data){ self.postMessage(value); value++; } }, false); })); //We add a listener to the worker to get the response and show it in the page worker1.addEventListener('message', function(e) { document.getElementById("result1").innerHTML = e.data; }, false); //Worker 2 var worker2 = new Worker(getScriptPath(function(){ self.addEventListener('message', function(e) { var value = 0; while(value <= e.data){ self.postMessage(value); value++; } }, false); })); worker2.addEventListener('message', function(e) { document.getElementById("result2").innerHTML = e.data; }, false); //Worker 3 var worker3 = new Worker(getScriptPath(function(){ self.addEventListener('message', function(e) { var value = 0; while(value <= e.data){ self.postMessage(value); value++; } }, false); })); worker3.addEventListener('message', function(e) { document.getElementById("result3").innerHTML = e.data; }, false); // Start and send data to our worker. worker1.postMessage(MAX_VALUE); worker2.postMessage(MAX_VALUE); worker3.postMessage(MAX_VALUE);
<div id="result1"></div> <div id="result2"></div> <div id="result3"></div>
使用HTML5“side-specs” 不需要再用setTimeout(),setInterval()等等来攻击javascript了 。
HTML5&Friends引入了JavaScript Web Workers规范。 它是一个asynchronous和独立运行脚本的API。
链接到规范和教程 。
JavaScript中没有真正的线程。 JavaScript是可扩展的语言,它允许你模仿其中的一些。 这是我前几天遇到的一个例子 。
在Javascript中没有真正的multithreading,但是可以使用setTimeout()
和asynchronousAJAX请求来获得asynchronous行为。
你究竟想要完成什么?
这里只是一个在Javascript中模拟multithreading的方法
现在我要创build3个线程来计算数字加法,数字可以用13来分割,数字可以用3到10000000000来分割,而这3个函数不能同时运行。 但是我会告诉你一个把这些函数同时recursion运行的技巧: jsFiddle
这段代码属于我。
身体的一部分
<div class="div1"> <input type="button" value="start/stop" onclick="_thread1.control ? _thread1.stop() : _thread1.start();" /><span>Counting summation of numbers till 10000000000</span> = <span id="1">0</span> </div> <div class="div2"> <input type="button" value="start/stop" onclick="_thread2.control ? _thread2.stop() : _thread2.start();" /><span>Counting numbers can be divided with 13 till 10000000000</span> = <span id="2">0</span> </div> <div class="div3"> <input type="button" value="start/stop" onclick="_thread3.control ? _thread3.stop() : _thread3.start();" /><span>Counting numbers can be divided with 3 till 10000000000</span> = <span id="3">0</span> </div>
Javascript部分
var _thread1 = {//This is my thread as object control: false,//this is my control that will be used for start stop value: 0, //stores my result current: 0, //stores current number func: function () { //this is my func that will run if (this.control) { // checking for control to run if (this.current < 10000000000) { this.value += this.current; document.getElementById("1").innerHTML = this.value; this.current++; } } setTimeout(function () { // And here is the trick! setTimeout is a king that will help us simulate threading in javascript _thread1.func(); //You cannot use this.func() just try to call with your object name }, 0); }, start: function () { this.control = true; //start function }, stop: function () { this.control = false; //stop function }, init: function () { setTimeout(function () { _thread1.func(); // the first call of our thread }, 0) } }; var _thread2 = { control: false, value: 0, current: 0, func: function () { if (this.control) { if (this.current % 13 == 0) { this.value++; } this.current++; document.getElementById("2").innerHTML = this.value; } setTimeout(function () { _thread2.func(); }, 0); }, start: function () { this.control = true; }, stop: function () { this.control = false; }, init: function () { setTimeout(function () { _thread2.func(); }, 0) } }; var _thread3 = { control: false, value: 0, current: 0, func: function () { if (this.control) { if (this.current % 3 == 0) { this.value++; } this.current++; document.getElementById("3").innerHTML = this.value; } setTimeout(function () { _thread3.func(); }, 0); }, start: function () { this.control = true; }, stop: function () { this.control = false; }, init: function () { setTimeout(function () { _thread3.func(); }, 0) } }; _thread1.init(); _thread2.init(); _thread3.init();
我希望这种方式会有所帮助。
你可以使用Narrative JavaScript ,这个编译器将你的代码转换成状态机,有效地让你模拟线程。 它通过向语言中添加一个“yielding”运算符(标记为' – >')来实现,该语言允许您在单个线性代码块中编写asynchronous代码。
今天应该出来的新的v8引擎支持它(我认为)
另一种可能的方法是在JavaScript环境中使用JavaScript解释器。
通过创build多个解释器并从主线程控制它们的执行,可以模拟在自己的环境中运行的每个线程的multithreading。
这种方法有点类似于networking工作者,但是你可以让解释者访问浏览器的全局环境。
我做了一个小项目来certificate这一点 。
在这个博客文章更详细的解释。
在原始的Javascript中,你可以做的最好的是使用less量的asynchronous调用(xmlhttprequest),但是这不是真正的线程和非常有限的。 Google Gears在浏览器中添加了一些API,其中一些可用于线程支持。
如果你不能或不想使用任何AJAX的东西,使用iframe或十! ;)您可以让stream程在与母版页并行的iframe中运行,而不用担心浏览器可比较的问题或点networkingAJAX等语法问题,您可以从母版页调用母版页的JavaScript(包括它所导入的JavaScript) iframe中。
例如,在父iframe中,一旦iframe内容已被加载(这是asynchronous部分),在父文档中调用egFunction()
)
parent.egFunction();
dynamic生成的iframes,所以主要的HTML代码是免费的,如果你想。
Javascript没有线程,但我们有工作人员。
如果不需要共享对象,工人可能是一个不错的select。
大多数浏览器实现将实际上跨所有核心传播工作,允许您利用所有核心。 你可以在这里看到一个演示。
我开发了一个名为task.js的库,这使得它非常容易。
task.js简化了CPU密集代码在所有内核上运行的接口(node.js和web)
一个例子是
function blocking (exampleArgument) { // block thread } // turn blocking pure function into a worker task const blockingAsync = task.wrap(blocking); // run task on a autoscaling worker pool blockingAsync('exampleArgumentValue').then(result => { // do something with result });
使用HTML5 规范,您不需要为相同的代码编写太多的JS,或者find一些黑客。
HTML5中引入的function之一是Web Workers ,它是在后台运行的JavaScript,与其他脚本无关,不会影响页面的性能。
几乎所有的浏览器都支持它:
Chrome – 4.0+
IE – 10.0+
Mozilla – 3.5+
Safari – 4.0+
歌剧 – 11.5+