Eine kurze Diskussion über Multithread-Operationen in Nodejs
Obwohl nodejs Single-Threaded ist, ermöglicht es dennoch Multithread-Operationen. Dieser Artikel beginnt mit Node-Threads, spricht über Multithread-Operationen in Nodejs und stellt die worker_threads-Vorlage vor.
Die Testumgebung für diesen Artikel:
System: macOS Mojave 10.14.2
CPU: 4 Kerne 2,3 GHz
Knoten: 10.15.1
[Empfohlenes Lernen: „nodejs-Tutorial“]
Apropos Node-Threads
Die meisten Leute verstehen, dass Node Single-Threaded ist, daher sollte die Anzahl der Threads nach dem Start von Node 1 sein. Lassen Sie uns ein Experiment durchführen, um das zu sehen. [Empfohlenes Lernen: „nodejs-Tutorial“]
setInterval(() => { console.log(new Date().getTime()) }, 3000)
Sie können sehen, dass der Node-Prozess 7 Threads belegt. Warum gibt es 7 Threads?
Wir alle wissen, dass der Kern von Node die v8-Engine ist. Nach dem Start von Node wird eine Instanz von v8 erstellt.
- Hauptthread: Code kompilieren und ausführen.
- Kompilierungs-/Optimierungsthread: Wenn der Hauptthread ausgeführt wird, kann der Code optimiert werden.
- Analysator-Thread: zeichnet die Codelaufzeit auf und analysiert sie, um eine Grundlage für die Optimierung der Codeausführung durch Crankshaft zu schaffen.
- Mehrere Threads zur Müllsammlung.
Wenn also oft gesagt wird, dass Node ein Single-Thread ist, bedeutet dies, dass die Ausführung von JavaScript Single-Thread ist, die Host-Umgebung von Javascript jedoch, egal ob Node oder Browser, Multi-Thread ist.
Node verfügt über zwei Compiler:
Full-Codegen: Kompilieren Sie js einfach und schnell in einfachen, aber langsamen mechanischen Code.
Crankshaft: Ein relativ komplexer Echtzeit-Optimierungscompiler, der leistungsstarken ausführbaren Code kompiliert.
Einige asynchrone E/A belegen zusätzliche Threads
Im obigen Beispiel lesen wir eine Datei, während der Timer ausgeführt wird:
const fs = require('fs') setInterval(() => { console.log(new Date().getTime()) }, 3000) fs.readFile('./index.html', () => {})
Die Anzahl der Threads beträgt 11, das liegt daran, dass es einige E/A gibt Vorgänge (DNS, FS) und einige CPU-intensive Berechnungen (Zlib, Crypto) in Node, Nodes Thread-Pool wird aktiviert und die Standardgröße des Thread-Pools beträgt 4, da die Anzahl der Threads 11 beträgt.
Wir können die Standardgröße des Thread-Pools manuell ändern:
process.env.UV_THREADPOOL_SIZE = 64
Ändern Sie die Threads mit einer Codezeile ganz einfach auf 71.
Ist der Cluster multithreaded?
Der einzelne Thread von Node bringt auch einige Probleme mit sich, z. B. eine unzureichende Auslastung der CPU, eine nicht abgefangene Ausnahme kann dazu führen, dass das gesamte Programm beendet wird usw. Da das Clustermodul in Node bereitgestellt wird, implementiert der Cluster die Kapselung von child_process und implementiert das Multiprozessmodell, indem untergeordnete Prozesse über die Fork-Methode erstellt werden. Beispielsweise ist pm2, das wir am häufigsten verwenden, der beste Vertreter unter ihnen.
Sehen wir uns eine Cluster-Demo an:
const cluster = require('cluster'); const http = require('http'); const numCPUs = require('os').cpus().length; if (cluster.isMaster) { console.log(`主进程 ${process.pid} 正在运行`); for (let i = 0; i < numCPUs; i++) { cluster.fork(); } cluster.on('exit', (worker, code, signal) => { console.log(`工作进程 ${worker.process.pid} 已退出`); }); } else { // 工作进程可以共享任何 TCP 连接。 // 在本例子中,共享的是 HTTP 服务器。 http.createServer((req, res) => { res.writeHead(200); res.end('Hello World'); }).listen(8000); console.log(`工作进程 ${process.pid} 已启动`); }
Sehen Sie sich zu diesem Zeitpunkt den Aktivitätsmonitor an:
Es gibt insgesamt 9 Prozesse, einer davon ist der Hauptprozess, die Anzahl der CPUs x die Anzahl der CPUs Kerne = 2 x 4 = 8 Teilprozesse verarbeiten.
Also ist weder child_process noch Cluster ein Multi-Thread-Modell, sondern ein Multi-Prozess-Modell. Obwohl Entwickler sich der Probleme des Single-Threaded-Modells bewusst sind, lösen sie das Problem nicht grundlegend und stellen eine Multiprozessmethode zur Simulation von Multithreading bereit. Aus den vorherigen Experimenten können wir erkennen, dass Node (V8) zwar selbst über Multithreading-Fähigkeiten verfügt, Entwickler diese Fähigkeit jedoch nicht sinnvoll nutzen können. Stattdessen nutzen sie Multithreading in gewisser Weise, das von der untersten Ebene von Node bereitgestellt wird. Node-Beamter sagte:
Sie können den integrierten Node-Worker-Pool verwenden, indem Sie ein C++-Add-on entwickeln. Erstellen Sie Ihr C++-Add-on mit NAN und verwenden Sie bei neueren Versionen N-API bietet eine reine JavaScript-Methode für den Zugriff auf den Worker-Pool von Node.
Aber für JavaScript-Entwickler gab es nie eine standardmäßige und benutzerfreundliche Möglichkeit, die Multithreading-Funktionen von Node zu nutzen.
Richtig – Node-Multithreading
Bis zur Veröffentlichung von Node 10.5.0 stellte der Beamte ein experimentelles Modul worker_threads zur Verfügung, um Node mit echten Multithreading-Funktionen auszustatten.
Werfen wir zunächst einen Blick auf die einfache Demo:
const { isMainThread, parentPort, workerData, threadId, MessageChannel, MessagePort, Worker } = require('worker_threads'); function mainThread() { for (let i = 0; i < 5; i++) { const worker = new Worker(__filename, { workerData: i }); worker.on('exit', code => { console.log(`main: worker stopped with exit code ${code}`); }); worker.on('message', msg => { console.log(`main: receive ${msg}`); worker.postMessage(msg + 1); }); } } function workerThread() { console.log(`worker: workerDate ${workerData}`); parentPort.on('message', msg => { console.log(`worker: receive ${msg}`); }), parentPort.postMessage(workerData); } if (isMainThread) { mainThread(); } else { workerThread(); }
Der obige Code öffnet fünf Unterthreads im Hauptthread und der Hauptthread sendet einfache Nachrichten an die Unterthreads.
由于 worker_thread 目前仍然处于实验阶段,所以启动时需要增加 --experimental-worker
flag,运行后观察活动监视器:
不多不少,正好多了五个子线程。
worker_thread 模块
worker_thread 核心代码
worker_thread 模块中有 4 个对象和 2 个类。
- isMainThread: 是否是主线程,源码中是通过
threadId === 0
进行判断的。 - MessagePort: 用于线程之间的通信,继承自 EventEmitter。
- MessageChannel: 用于创建异步、双向通信的通道实例。
- threadId: 线程 ID。
- Worker: 用于在主线程中创建子线程。第一个参数为 filename,表示子线程执行的入口。
- parentPort: 在 worker 线程里是表示父进程的 MessagePort 类型的对象,在主线程里为 null
- workerData: 用于在主进程中向子进程传递数据(data 副本)
来看一个进程通信的例子:
const assert = require('assert'); const { Worker, MessageChannel, MessagePort, isMainThread, parentPort } = require('worker_threads'); if (isMainThread) { const worker = new Worker(__filename); const subChannel = new MessageChannel(); worker.postMessage({ hereIsYourPort: subChannel.port1 }, [subChannel.port1]); subChannel.port2.on('message', (value) => { console.log('received:', value); }); } else { parentPort.once('message', (value) => { assert(value.hereIsYourPort instanceof MessagePort); value.hereIsYourPort.postMessage('the worker is sending this'); value.hereIsYourPort.close(); }); }
更多详细用法可以查看官方文档。
多进程 vs 多线程
根据大学课本上的说法:“进程是资源分配的最小单位,线程是CPU调度的最小单位”,这句话应付考试就够了,但是在实际工作中,我们还是要根据需求合理选择。
下面对比一下多线程与多进程:
属性 | 多进程 | 多线程 | 比较 |
---|---|---|---|
数据 | 数据共享复杂,需要用IPC;数据是分开的,同步简单 | 因为共享进程数据,数据共享简单,同步复杂 | 各有千秋 |
CPU、内存 | 占用内存多,切换复杂,CPU利用率低 | 占用内存少,切换简单,CPU利用率高 | 多线程更好 |
销毁、切换 | 创建销毁、切换复杂,速度慢 | 创建销毁、切换简单,速度很快 | 多线程更好 |
coding | 编码简单、调试方便 | 编码、调试复杂 | 多进程更好 |
可靠性 | 进程独立运行,不会相互影响 | 线程同呼吸共命运 | 多进程更好 |
分布式 | 可用于多机多核分布式,易于扩展 | 只能用于多核分布式 | 多进程更好 |
上述比较仅表示一般情况,并不绝对。
work_thread 让 Node 有了真正的多线程能力,算是不小的进步。
更多编程相关知识,请访问:编程视频!!
Das obige ist der detaillierte Inhalt vonEine kurze Diskussion über Multithread-Operationen in Nodejs. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Heiße KI -Werkzeuge

Undresser.AI Undress
KI-gestützte App zum Erstellen realistischer Aktfotos

AI Clothes Remover
Online-KI-Tool zum Entfernen von Kleidung aus Fotos.

Undress AI Tool
Ausziehbilder kostenlos

Clothoff.io
KI-Kleiderentferner

AI Hentai Generator
Erstellen Sie kostenlos Ai Hentai.

Heißer Artikel

Heiße Werkzeuge

Notepad++7.3.1
Einfach zu bedienender und kostenloser Code-Editor

SublimeText3 chinesische Version
Chinesische Version, sehr einfach zu bedienen

Senden Sie Studio 13.0.1
Leistungsstarke integrierte PHP-Entwicklungsumgebung

Dreamweaver CS6
Visuelle Webentwicklungstools

SublimeText3 Mac-Version
Codebearbeitungssoftware auf Gottesniveau (SublimeText3)

Heiße Themen

Die Behandlung von Funktionsausnahmen in C++ ist in Multithread-Umgebungen besonders wichtig, um Thread-Sicherheit und Datenintegrität sicherzustellen. Mit der try-catch-Anweisung können Sie bestimmte Arten von Ausnahmen abfangen und behandeln, wenn sie auftreten, um Programmabstürze oder Datenbeschädigungen zu verhindern.

Die Hauptunterschiede zwischen Node.js und Java sind Design und Funktionen: Ereignisgesteuert vs. Thread-gesteuert: Node.js ist ereignisgesteuert und Java ist Thread-gesteuert. Single-Threaded vs. Multi-Threaded: Node.js verwendet eine Single-Threaded-Ereignisschleife und Java verwendet eine Multithread-Architektur. Laufzeitumgebung: Node.js läuft auf der V8-JavaScript-Engine, während Java auf der JVM läuft. Syntax: Node.js verwendet JavaScript-Syntax, während Java Java-Syntax verwendet. Zweck: Node.js eignet sich für I/O-intensive Aufgaben, während Java für große Unternehmensanwendungen geeignet ist.

Parallelitäts- und Multithreading-Techniken mithilfe von Java-Funktionen können die Anwendungsleistung verbessern, einschließlich der folgenden Schritte: Parallelitäts- und Multithreading-Konzepte verstehen. Nutzen Sie die Parallelitäts- und Multithreading-Bibliotheken von Java wie ExecutorService und Callable. Üben Sie Fälle wie die Multithread-Matrixmultiplikation, um die Ausführungszeit erheblich zu verkürzen. Genießen Sie die Vorteile einer erhöhten Reaktionsgeschwindigkeit der Anwendung und einer optimierten Verarbeitungseffizienz durch Parallelität und Multithreading.

Um eine Verbindung zu einer MySQL-Datenbank herzustellen, müssen Sie die folgenden Schritte ausführen: Installieren Sie den MySQL2-Treiber. Verwenden Sie mysql2.createConnection(), um ein Verbindungsobjekt zu erstellen, das die Hostadresse, den Port, den Benutzernamen, das Passwort und den Datenbanknamen enthält. Verwenden Sie „connection.query()“, um Abfragen durchzuführen. Verwenden Sie abschließend Connection.end(), um die Verbindung zu beenden.

PHP-Multithreading bezieht sich auf die gleichzeitige Ausführung mehrerer Aufgaben in einem Prozess, was durch die Erstellung unabhängig laufender Threads erreicht wird. Sie können die Pthreads-Erweiterung in PHP verwenden, um Multithreading-Verhalten zu simulieren. Nach der Installation können Sie die Thread-Klasse zum Erstellen und Starten von Threads verwenden. Wenn beispielsweise eine große Datenmenge verarbeitet wird, können die Daten in mehrere Blöcke unterteilt und eine entsprechende Anzahl von Threads erstellt werden, um sie gleichzeitig zu verarbeiten, um die Effizienz zu verbessern.

Mutexe werden in C++ verwendet, um gemeinsam genutzte Multithread-Ressourcen zu verarbeiten: Erstellen Sie Mutexe über std::mutex. Verwenden Sie mtx.lock(), um einen Mutex zu erhalten und exklusiven Zugriff auf gemeinsam genutzte Ressourcen bereitzustellen. Verwenden Sie mtx.unlock(), um den Mutex freizugeben.

In einer Multithread-Umgebung steht die C++-Speicherverwaltung vor den folgenden Herausforderungen: Datenrennen, Deadlocks und Speicherlecks. Zu den Gegenmaßnahmen gehören: 1. Verwendung von Synchronisationsmechanismen, wie Mutexe und atomare Variablen; 3. Verwendung von intelligenten Zeigern; 4. Implementierung von Garbage Collection;

Node.js ist eine JavaScript-Laufzeitumgebung und npm ist ihr Paketmanager. Die beiden arbeiten zusammen, um Entwicklern das Schreiben serverseitiger Programme in JavaScript, die Verwendung von Modulen von Drittanbietern und die einfache Verwaltung von Modulen zu ermöglichen.
