Frage

Gibt es eine Möglichkeit, Multithreading in JavaScript durchzuführen?

War es hilfreich?

Lösung

Sehen http://caniuse.com/#search=worker für die aktuellsten Support-Informationen.

Das Folgende war der Stand der Unterstützung um 2009.


Die Wörter, nach denen Sie googeln möchten, sind JavaScript-Worker-Threads

Abgesehen von Getriebe Im Moment ist nichts verfügbar, aber es wird viel darüber geredet, wie man das umsetzen kann, also schaue ich mir diese Frage an, denn die Antwort wird sich in Zukunft zweifellos ändern.

Hier ist die relevante Dokumentation für Gears: WorkerPool-API

WHATWG hat einen Empfehlungsentwurf für Arbeitsthreads: Web-Worker

Und es gibt auch Mozillas DOM-Worker-Threads


Aktualisieren: Juni 2009, aktueller Stand der Browserunterstützung für JavaScript-Threads

Firefox 3.5 hat Web-Worker.Einige Demos von Web Workern, wenn Sie sie in Aktion sehen möchten:

Das Gears-Plugin kann auch in Firefox installiert werden.

Safari 4, und das WebKit-Nachtbücher Habe Worker-Threads:

Chrom verfügt über Gears, sodass Threads ausgeführt werden können, obwohl eine Bestätigungsaufforderung vom Benutzer erforderlich ist (und eine andere API als Web-Worker verwendet wird, obwohl es in jedem Browser mit installiertem Gears-Plugin funktioniert):

  • Google Gears WorkerPool-Demo (Kein gutes Beispiel, da es zu schnell läuft, um es in Chrome und Firefox zu testen, obwohl der IE es langsam genug ausführt, um zu sehen, dass es die Interaktion blockiert.)

IE8 Und IE9 Threads können nur erstellt werden, wenn das Gears-Plugin installiert ist

Andere Tipps

Andere Möglichkeit, Multithreading und Asynchronität in JavaScript durchzuführen

Vor HTML5 erlaubte JavaScript nur die Ausführung eines Threads pro Seite.

Es gab eine knifflige Möglichkeit, eine asynchrone Ausführung zu simulieren Ertrag, setTimeout(), setInterval(), XMLHttpRequest oder Ereignishandler (Am Ende dieses Beitrags finden Sie ein Beispiel mit Ertrag Und setTimeout()).

Aber mit HTML5 können wir jetzt Worker Threads verwenden, um die Ausführung von Funktionen zu parallelisieren.Hier ist ein Anwendungsbeispiel.


Echtes Multithreading

Multithreading:JavaScript-Worker-Threads

HTML5 führte Web-Worker-Threads ein (siehe: Browserkompatibilitäten)
Notiz:IE9 und frühere Versionen unterstützen dies nicht.

Bei diesen Arbeitsthreads handelt es sich um JavaScript-Threads, die im Hintergrund ausgeführt werden, ohne die Leistung der Seite zu beeinträchtigen.Weitere Informationen zu Web-Worker Lesen Sie die Dokumentation oder dieses Tutorial.

Hier ist ein einfaches Beispiel mit 3 Web-Worker-Threads, die bis MAX_VALUE zählen und den aktuell berechneten Wert auf unserer Seite anzeigen:

//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>

Wir können sehen, dass die drei Threads gleichzeitig ausgeführt werden und ihren aktuellen Wert auf der Seite ausgeben.Sie frieren die Seite nicht ein, da sie im Hintergrund mit getrennten Threads ausgeführt werden.


Multithreading:mit mehreren Iframes

Eine andere Möglichkeit, dies zu erreichen, ist die Verwendung mehrerer Iframes, jeder führt einen Thread aus.Wir können das geben iframe einige Parameter durch die URL und die iframe kann mit seinen Eltern kommunizieren, um das Ergebnis zu erhalten und es auszudrucken (die iframe muss in derselben Domäne liegen).

Dieses Beispiel funktioniert nicht in allen Browsern! Iframes wird normalerweise im selben Thread/Prozess wie die Hauptseite ausgeführt (aber Firefox und Chromium scheinen damit unterschiedlich umzugehen).

Da das Code-Snippet nicht mehrere HTML-Dateien unterstützt, stelle ich hier nur die verschiedenen Codes bereit:

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);
    }
})();

Simulieren Sie Multithreading

Single-Thread:Emulieren Sie die JavaScript-Parallelität mit setTimeout()

Der „naive“ Weg wäre, die Funktion auszuführen setTimeout() nacheinander so:

setTimeout(function(){ /* Some tasks */ }, 0);
setTimeout(function(){ /* Some tasks */ }, 0);
[...]

Aber diese Methode funktioniert nicht denn jede Aufgabe wird nacheinander ausgeführt.

Wir können die asynchrone Ausführung simulieren, indem wir die Funktion wie folgt rekursiv aufrufen:

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>

Wie Sie sehen, ist diese zweite Methode sehr langsam und friert den Browser ein, da sie den Hauptthread zum Ausführen der Funktionen verwendet.


Single-Thread:Emulieren Sie die JavaScript-Parallelität mit yield

Ertrag ist eine neue Funktion in ECMAScript 6, es funktioniert nur auf der ältesten Version von Firefox und Chrome (in Chrome müssen Sie es aktivieren). Experimentelles JavaScript Erscheinen in chrome://flags/#enable-javascript-harmony).

Das Schlüsselwort yield bewirkt, dass die Ausführung der Generatorfunktion angehalten wird und der Wert des Ausdrucks, der auf das Schlüsselwort yield folgt, an den Aufrufer des Generators zurückgegeben wird.Man kann es sich als eine Generator-basierte Version des Schlüsselworts return vorstellen.

Mit einem Generator können Sie die Ausführung einer Funktion unterbrechen und später wieder aufnehmen.Mit einem Generator können Sie Ihre Funktionen mit einer Technik namens planen Trampolin springen.

Hier ist das Beispiel:

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>

Mit den HTML5 „Side-Specs“ Sie müssen kein Javascript mehr hacken mit setTimeout(), setInterval() usw.

HTML5 & Friends führt das Javascript ein Web-Worker Spezifikation.Es handelt sich um eine API zum asynchronen und unabhängigen Ausführen von Skripten.

Links zum Spezifikation und ein Lernprogramm.

In JavaScript gibt es kein echtes Threading.Da JavaScript eine formbare Sprache ist, können Sie einiges davon emulieren.Hier ist ein Beispiel Ich bin neulich darauf gestoßen.

Es gibt kein echtes Multithreading in Javascript, aber Sie können mit asynchrones Verhalten erzielen setTimeout() und asynchrone AJAX-Anfragen.

Was genau wollen Sie erreichen?

Hier ist nur ein Weg dazu simulieren Multithreading in Javascript

Jetzt werde ich 3 Threads erstellen, die die Zahlenaddition berechnen, Zahlen können durch 13 geteilt werden und Zahlen können durch 3 bis 10000000000 geteilt werden.Und diese drei Funktionen können nicht gleichzeitig mit der Bedeutung von Parallelität ausgeführt werden.Aber ich zeige Ihnen einen Trick, mit dem diese Funktionen gleichzeitig rekursiv ausgeführt werden: jsFiddle

Dieser Code gehört mir.

Körperteil

    <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-Teil

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();

Ich hoffe, dieser Weg wird hilfreich sein.

Du könntest benutzen Narratives JavaScript, ein Compiler, der Ihren Code in eine Zustandsmaschine umwandelt und es Ihnen so ermöglicht, Threading effektiv zu emulieren.Dies geschieht durch das Hinzufügen eines „nachgebenden“ Operators (notiert als „->“) zur Sprache, der es Ihnen ermöglicht, asynchronen Code in einem einzelnen, linearen Codeblock zu schreiben.

Der neue V8-Motor, der sollte rauskommen Heute unterstützt es (glaube ich)

Eine andere mögliche Methode ist die Verwendung eines Javascript-Interpreters in der Javascript-Umgebung.

Indem Sie mehrere Interpreter erstellen und deren Ausführung vom Hauptthread aus steuern, können Sie Multithreading simulieren, wobei jeder Thread in seiner eigenen Umgebung ausgeführt wird.

Der Ansatz ähnelt in gewisser Weise dem von Web Workern, Sie gewähren dem Interpreter jedoch Zugriff auf die globale Browserumgebung.

Ich habe ein kleines Projekt dazu gemacht demonstrieren Sie dies.

Eine ausführlichere Erklärung in dieser Blogbeitrag.

In rohem Javascript können Sie am besten die wenigen asynchronen Aufrufe (xmlhttprequest) verwenden, aber das ist kein echtes Threading und sehr eingeschränkt. Google Gears Fügt dem Browser eine Reihe von APIs hinzu, von denen einige zur Threading-Unterstützung verwendet werden können.

Wenn Sie keine AJAX-Inhalte verwenden können oder wollen, verwenden Sie einen oder zehn Iframes!;) Sie können Prozesse in Iframes parallel zur Masterseite ausführen lassen, ohne sich Gedanken über browserübergreifende Vergleichsprobleme oder Syntaxprobleme mit Dot Net AJAX usw. machen zu müssen, und Sie können das JavaScript der Masterseite (einschließlich des JavaScript, das sie importiert hat) von einem aufrufen iframe.

Z. B. in einem übergeordneten Iframe zum Aufrufen egFunction() im übergeordneten Dokument, sobald der Iframe-Inhalt geladen wurde (das ist der asynchrone Teil)

parent.egFunction();

Generieren Sie bei Bedarf auch die Iframes dynamisch, sodass der Haupt-HTML-Code frei davon ist.

Javascript hat keine Threads, aber wir haben Worker.

Worker sind möglicherweise eine gute Wahl, wenn Sie keine gemeinsam genutzten Objekte benötigen.

Die meisten Browser-Implementierungen verteilen die Worker tatsächlich auf alle Kerne, sodass Sie alle Kerne nutzen können.Sie können eine Demo davon sehen Hier.

Ich habe eine Bibliothek namens entwickelt task.js Das macht es sehr einfach.

task.js Vereinfachte Schnittstelle für die Ausführung von CPU-intensivem Code auf allen Kernen (node.js und Web)

Ein Beispiel wäre

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
});

Mit HTML5 Spezifikation Sie müssen dafür nicht zu viel JS schreiben oder ein paar Hacks finden.

Eine der in HTML5 eingeführten Funktionen ist Web-Worker Hierbei handelt es sich um JavaScript, das unabhängig von anderen Skripten im Hintergrund ausgeführt wird, ohne die Leistung der Seite zu beeinträchtigen.

Es wird in fast allen Browsern unterstützt:

Chrome – 4.0+

IE – 10.0+

Mozilla - 3.5+

Safari – 4.0+

Oper – 11.5+

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top