有没有办法在JavaScript中进行多线程处理?
在JavaScript中执行多线程和异步的不同方法
在HTML5之前,JavaScript仅允许每页执行一个线程。
有以模拟与异步执行一些哈克的方式产率,setTimeout()
,setInterval()
,XMLHttpRequest
或事件处理程序(看到此信息的用于与例如端部收率和setTimeout()
)。
但是,借助HTML5,我们现在可以使用工作线程来并行执行功能。这是一个使用示例。
真正的多线程
多线程:JavaScript Worker线程
注意:IE9和更早版本不支持它。
这是一个简单的示例,其中包含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>
我们可以看到这三个线程是并发执行的,并在页面中打印它们的当前值。它们不会冻结页面,因为它们是在后台用单独的线程执行的。
多线程:具有多个iframe
实现此目标的另一种方法是使用多个iframe,每个iframe都会执行一个线程。我们可以通过URL 为iframe提供一些参数,并且iframe可以与其父级进行通信以获取结果并将其打印回去(iframe必须位于同一域中)。
此示例不适用于所有浏览器! iframe通常与主页在同一线程/进程中运行(但Firefox和Chromium似乎处理方式有所不同)。
由于该代码段不支持多个HTML文件,因此我将在此处提供不同的代码:
index.html:
//The 3 iframes containing the code (take the thread id in param)
<iframe id="threadFrame1" src="thread.html?id=1"></iframe>
<iframe id="threadFrame2" src="thread.html?id=2"></iframe>
<iframe id="threadFrame3" src="thread.html?id=3"></iframe>
//Divs that shows the result
<div id="result1"></div>
<div id="result2"></div>
<div id="result3"></div>
<script>
//This function is called by each iframe
function threadResult(threadId, result) {
document.getElementById("result" + threadId).innerHTML = result;
}
</script>
thread.html:
//Get the parameters in the URL: http://stackoverflow.com/a/1099670/2576706
function getQueryParams(paramName) {
var qs = document.location.search.split('+').join(' ');
var params = {}, tokens, re = /[?&]?([^=]+)=([^&]*)/g;
while (tokens = re.exec(qs)) {
params[decodeURIComponent(tokens[1])] = decodeURIComponent(tokens[2]);
}
return params[paramName];
}
//The thread code (get the id from the URL, we can pass other parameters as needed)
var MAX_VALUE = 100000;
(function thread() {
var threadId = getQueryParams('id');
for(var i=0; i<MAX_VALUE; i++){
parent.threadResult(threadId, i);
}
})();
模拟多线程
单线程:使用setTimeout()
模拟JavaScript并发
“幼稚”的方式是setTimeout()
像下面这样一个接一个地执行函数:
setTimeout(function(){ /* Some tasks */ }, 0);
setTimeout(function(){ /* Some tasks */ }, 0);
[...]
但是此方法不起作用,因为每个任务都会一个接一个地执行。
我们可以通过递归调用函数来模拟异步执行,如下所示:
var MAX_VALUE = 10000;
function thread1(value, maxValue){
var me = this;
document.getElementById("result1").innerHTML = value;
value++;
//Continue execution
if(value<=maxValue)
setTimeout(function () { me.thread1(value, maxValue); }, 0);
}
function thread2(value, maxValue){
var me = this;
document.getElementById("result2").innerHTML = value;
value++;
if(value<=maxValue)
setTimeout(function () { me.thread2(value, maxValue); }, 0);
}
function thread3(value, maxValue){
var me = this;
document.getElementById("result3").innerHTML = value;
value++;
if(value<=maxValue)
setTimeout(function () { me.thread3(value, maxValue); }, 0);
}
thread1(0, MAX_VALUE);
thread2(0, MAX_VALUE);
thread3(0, MAX_VALUE);
<div id="result1"></div>
<div id="result2"></div>
<div id="result3"></div>
如您所见,第二种方法非常慢并且会冻结浏览器,因为它使用主线程来执行功能。
单线程:使用yield模拟JavaScript并发
Yield是 ECMAScript 6中的一项新功能,仅在Firefox和Chrome的最旧版本上有效(在Chrome中,您需要启用出现在 chrome:// flags /#enable-javascript-harmony中的实验性JavaScript)。
yield关键字使生成器函数的执行暂停,并且yield关键字之后的表达式的值将返回到生成器的调用者。可以将其视为return关键字的基于生成器的版本。
生成器使您可以中止函数的执行并在以后继续执行。生成器可用于通过称为蹦床的技术来安排您的功能。
这是示例:
var MAX_VALUE = 10000;
Scheduler = {
_tasks: [],
add: function(func){
this._tasks.push(func);
},
start: function(){
var tasks = this._tasks;
var length = tasks.length;
while(length>0){
for(var i=0; i<length; i++){
var res = tasks[i].next();
if(res.done){
tasks.splice(i, 1);
length--;
i--;
}
}
}
}
}
function* updateUI(threadID, maxValue) {
var value = 0;
while(value<=maxValue){
yield document.getElementById("result" + threadID).innerHTML = value;
value++;
}
}
Scheduler.add(updateUI(1, MAX_VALUE));
Scheduler.add(updateUI(2, MAX_VALUE));
Scheduler.add(updateUI(3, MAX_VALUE));
Scheduler.start()
<div id="result1"></div>
<div id="result2"></div>
<div id="result3"></div>
主要内容:一、MySql中的线程,二、主要方式,三、源码流程,四、总结一、MySql中的线程 在mysql中,每一个连接上来,就会分配给一个相关的THD数据类。在前面的分析中可以看到,连接器(Connectors)连接到的直接就是连接池,在连接池的线程处理中分为三部分,即一对一(一个连接对应一个线程),多对一(多个连接对应一个线程)和线程池(多对多)。 线程池和线程可以针对不同的具体场景来处理具体的事务,这样既兼顾了效率又提高了适应性,对于新手来说,这就是设计的一个
正在使用和原始人的线程吗? 许多月前,我学会了如何在Android上编写多线程Java代码。我记得我必须创建线程、启动线程等等。 现在我正在学习Javascript,我刚刚学习了和。 例如: 这看起来比我以前做的简单多了,而且更直观。 将首先启动,然后启动快速函数(),然后将等待,直到两个函数在日志记录之前解决-和和可能同时运行。我希望这最终取决于浏览器是否是独立的线程。但看起来它走路和说话就像粗
以下测验提供与Javascript Framework相关的多项选择题(MCQ)。 您必须阅读所有给定的答案并单击正确的答案。 如果您不确定答案,则可以使用“ Show Answer按钮Show Answer 。 您可以使用“ Next Quiz按钮在Next Quiz中检查新的问题集。 问题1 - 关于JavaScript的功能,以下哪项是正确的? A - JavaScript是一种轻量级的解释
我听说Python中的线程不容易处理,而且它们与tkinter的关系更加复杂。 我有以下问题。我有两个类,一个用于GUI,另一个用于无限进程。首先,我启动GUI类,然后启动无限进程类。我希望当您关闭GUI时,它也会完成无限过程,程序也会结束。 代码的简化版本如下: 单击关闭按钮(右上角)时,控制台中会出现以下错误: 我不知道为什么会这样,也不知道这意味着什么。
9.8. Goroutines和线程 在上一章中我们说goroutine和操作系统的线程区别可以先忽略。尽管两者的区别实际上只是一个量的区别,但量变会引起质变的道理同样适用于goroutine和线程。现在正是我们来区分开两者的最佳时机。 9.8.1. 动态栈 每一个OS线程都有一个固定大小的内存块(一般会是2MB)来做栈,这个栈会用来存储当前正在被调用或挂起(指在调用其它函数时)的函数的内部变量。
问题内容: 我对Javascript的单线程性质有疑问。 此代码的结果是。如您所见,这之后让我感到奇怪的是,在单线程环境中是否应该不应该这样做?如果没有,那么JS怎么知道第二个应该在第一个之前完成?难道不应该有两个线程可以同时工作以完成两个s以便进行通知吗? 问题答案: JavaScript(在浏览器中) 不能 同时运行2。 最多 一个 的的回调可以同时执行-因为有 一个 JavaScript执行