Parallelität und Multithreading in JavaScript: Von A bis Z

Online Python-Trainer für Anfänger

Lernen Sie Python einfach ohne theoretische Überlastung. Lösen Sie praktische Aufgaben mit automatischer Überprüfung und schreiben Sie Code direkt im Browser.

Kurs starten

Parallelität und Multithreading in JavaScript: Von A bis Z



JavaScript ist historisch gesehen eine Single-Thread-Sprache, die im Rahmen des ereignisgesteuerten Programmierparadigmas arbeitet. Das moderne JavaScript (insbesondere in der Node.js-Umgebung) bietet jedoch leistungsstarke Werkzeuge für die Arbeit mit Parallelität und Multithreading. In diesem Artikel werden wir uns ansehen, wie Event Loop, Promises, async/await, Worker Threads und Clusterbildung funktionieren und wie Sie diese Mechanismen nutzen können, um die Leistung Ihrer Anwendungen zu steigern.



1. Event Loop: Die Grundlage der Parallelität in JavaScript



Der Event Loop ist das Herzstück des asynchronen JavaScript-Modells. Er ermöglicht die Verarbeitung vieler Operationen, ohne den Hauptausführungs-Thread zu blockieren. In Node.js verwaltet der Event Loop Aufgabenwarteschlangen (Macrotasks und Microtasks) und gewährleistet so eine nicht blockierende Ein-/Ausgabe.



Beispiel für die Funktionsweise des Event Loops:



console.log('Start');

setTimeout(() => { console.log('Timer 1');}, 0);

process.nextTick(() => { console.log('nextTick');});

Promise.resolve().then(() => { console.log('Promise');});

console.log('Ende');

// Ausgabe:// Start// Ende// nextTick// Promise// Timer 1


Es ist wichtig, die Ausführungsreihenfolge zu verstehen: Synchroner Code → Microtasks (process.nextTick, Promise.then) → Macrotasks (setTimeout, setInterval).



2. Promises und async/await: Asynchronität verwalten



Promises sind Objekte, die das Ergebnis einer asynchronen Operation darstellen. Sie helfen, die „Callback-Hölle“ zu vermeiden und ermöglichen die Erstellung von Aufrufketten. async/await ist syntaktischer Zucker für Promises, der asynchronen Code wie synchronen Code aussehen lässt.



Beispiel mit async/await:



const fetchData = async (url) => {  const response = await fetch(url);  if (!response.ok) {    throw new Error(`HTTP-Fehler: ${response.status}`);  }  return await response.json();};

const main = async () => { try { const data = await fetchData('https://api.example.com/data'); console.log('Empfangene Daten:', data); } catch (error) { console.error('Fehler:', error.message); }};

main();


Dieser Ansatz ermöglicht die parallele Ausführung mehrerer asynchroner Operationen mit Promise.all():



const [user, posts] = await Promise.all([  fetchUser(userId),  fetchPosts(userId)]);console.log(user, posts);


3. Worker Threads: Echtes Multithreading in Node.js



Seit Node.js 10.5.0 bietet das Modul worker_threads die Möglichkeit, echte Threads für CPU-intensive Aufgaben zu erstellen. Jeder Worker läuft in einem separaten Thread mit einer eigenen V8-Instanz.



Beispiel für die Erstellung eines Workers:



// main.jsconst { Worker } = require('worker_threads');

const runWorker = (workerData) => { return new Promise((resolve, reject) => { const worker = new Worker('./worker.js', { workerData });

worker.on('message', resolve); worker.on('error', reject); worker.on('exit', (code) => { if (code !== 0) { reject(new Error(`Worker wurde mit Code ${code} beendet`)); } }); });};

const main = async () => { const result = await runWorker({ iterations: 1000000 }); console.log('Ergebnis:', result);};

main();


// worker.jsconst { parentPort, workerData } = require('worker_threads');

const heavyComputation = (iterations) => { let result = 0; for (let i = 0; i < iterations; i++) { result += Math.sqrt(i); } return result;};

const result = heavyComputation(workerData.iterations);parentPort.postMessage(result);


Worker Threads eignen sich ideal für Aufgaben, die den Event Loop blockieren: Bildverarbeitung, mathematische Berechnungen, Parsen großer Dateien.



4. Clusterbildung: Skalierung auf mehrere Prozesse

\

Blogs

Buchempfehlungen