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 4WebKit nightlies都有工作线程:

  • JavaScript Ray Tracer

Chrome浏览器已经embedded了Gears,所以它可以执行线程,虽然它需要用户的确认提示(并且使用不同的API给web工作者,尽pipe它可以在任何安装了Gears插件的浏览器中运行):

  • 谷歌齿轮WorkerPool演示 (不是一个很好的例子,因为它运行速度太快,无法在Chrome和Firefox中testing,尽pipeIE运行速度足以让它阻止交互)

IE8IE9只能安装Gears插件

在JavaScript中使用multithreading和asynchronous的不同方式

在HTML5之前,JavaScript只允许每页执行一个线程。

YieldsetTimeout()setInterval()XMLHttpRequest事件处理程序来模拟一个asynchronous的执行有一些奇怪的方法(有关yieldsetTimeout()的例子,请参阅本文结尾部分)。

但是使用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+