Czy NodeJs jest jednowątkowy?
Node.js uruchamia kod JavaScript w jednym wątku, co oznacza, że Twój kod może wykonywać tylko jedno zadanie na raz. Ale sam Node.js jest wielowątkowy i zapewnia ukryte wątki poprzez bibliotekę `libuv`, która obsługuje operacje wejścia/wyjścia, takie jak odczyt plików z dysku lub żądania sieciowe. Dzięki wykorzystaniu ukrytych wątków Node.js udostępnia metody asynchroniczne, które pozwalają Twojemu kodowi wykonywać żądania we/wy bez blokowania głównego wątku.
Node.js przedstawił nam moduł worker-threads. Moduł ten umożliwia równoległe tworzenie wątków i wykonywanie zadań Javascript. Jeśli wątek zakończy zadanie, wysyła wiadomość do głównego wątku zawierającą wynik, abyśmy mogli go użyć w głównym wątku. Wątki robocze nie blokują głównego wątku, więc możemy podzielić i rozdzielić nasze zadanie na wiele części, aby je zoptymalizować.
Zróbmy z tego przykład i przyjrzyjmy się mu bliżej.
Tworzymy projekt Nodejs i instalujemy framework Express
mkdir multiple-thread
cd multiple-thread
npm init -y
npm install express
Przede wszystkim są procesy i wątki. Powinniśmy znać różnice między nimi.
Co to jest proces?
Proces uruchamia program w systemie operacyjnym. Może wykonywać jedno zadanie na raz.
Przyjrzyjmy się bliżej procesowi bliżej. Utwórz plik JS i zarejestruj proces.
//ex-process.js
const processName = process.argv.slice(2)[0]
let count = 0;
while(true){
count++;
if(count === 3333 || count=== 6666){
console.log(`${processName}: ${count}`)
}
}
node ex-process.js FirstEx &
// & symbol means the Node program to run in the background, so we can use
our teminal for other works
Output
[1] 82942
FirstEx: 3333
FirstEx: 6666
ps |grep node
Output
82942 ttys001 2:38.85 node ex-process.js FirstEx
83105 ttys001 0:00.00 grep node
Wątki to stosunkowo lekki sposób implementacji wielu ścieżek wykonywania w aplikacji. Na poziomie systemu programy działają obok siebie, a system przydziela czas wykonania każdemu programowi na podstawie jego potrzeb i potrzeb innych programów.
Zakodujmy Express Server z trasami nieblokującymi i trasami blokującymi
Zakodujmy normalną trasę blokowania dla użytkowników. w app.js;
const express = require('express');
const app = express();
app.get('/hello', (req,res)=>{
res.status(200).send(`Hello`);
})
app.get('/blocking-route', (req,res)=>{
console.log('Blocking route called')
let counter = 0;
for (let i = 0; i < 15_000_000_000; i++) {
counter++;
}
res.status(200).send(`result is ${counter}`);
})
app.listen(7333, ()=> console.log('Server started on port 7333'));
Nie odpowiada, dopóki nie blocking-routeskończy i nie odesła odpowiedzi.
Dlaczego nie odpowiedział nam od razu?
W tym przykładzie pętla for związana z procesorem blokuje główny wątek. Gdy główny wątek jest zablokowany, Node.js nie może przetwarzać żadnych zapytań, dopóki proces związany z procesorem nie zostanie zakończony. więc żadna z innych tras nie /hellodziała podczas /blocking-routeładowania trasy.
Tak więc, jeśli mamy interfejs API, który ma tysiące jednoczesnych GETżądań do nieblokującej trasy, takiej jak /hello, tylko jedno żądanie do /blocking-routezablokuje wszystkie trasy w interfejsie API. Oznacza to, że wszystkie trasy aplikacji przestają odpowiadać.
DAAA IT's javascript, nie możemy użyć innego wątku
Koleś To nie tylko JS. To Nodejs. Możemy odciążyć zadanie związane z procesorem za pomocą wątków roboczych.
Przede wszystkim powinniśmy sprawdzić nasze rdzenie z nprocdowództwem
nproc
output
8
Stwórzmy kolejny plik JS, taki jak worker.js, nazwa zależy od Ciebie. W tym pliku wykonujemy zadania intensywnie korzystające z procesora
//worker.js
const { parentPort } = require("worker_threads");
let counter = 0;
console.log("Worker started");
for (let i = 0; i < 15_000_000_000; i++) {
counter++;
}
parentPort.postMessage(counter);
//app.js
const express = require("express");
const { Worker } = require("worker_threads");
const app = express();
app.get("/blocking-route", async (req, res) => {
console.log("Blocking route called");
let counter = 0;
for (let i = 0; i < 15_000_000_000; i++) {
counter++;
}
res.status(200).send(`result is ${counter}`);
});
app.get("/hello", (req, res) => {
res.status(200).send(`Hello`);
});
app.get("/non-blocking-route", async (req, res) => {
console.log("Non-blocking route called");
const worker = new Worker("./worker.js");
worker.on("message", (data) => {
res.status(200).send(`result is ${data}`);
});
worker.on("error", (err) => {
res.status(404).send(` error ${err}`);
});
console.log("I am not blocked");
});
app.listen(7333, () => console.log("Server started on port 7333"));
Uruchommy serwer z node app.js. Otwórz przeglądarkę i przejdź, http://localhost:7333/non-blocking-routezanim zwróci odpowiedź, przejdź do http://localhost:7333/hello. Czy zdałeś sobie z tego sprawę? Odpowiedź otrzymujemy natychmiast. Nie ma blokady. Nie czekaliśmy, aż inne trasy się załadują. Ponieważ zadanie związane z procesorem jest odciążane i działa w innym wątku, a główny wątek obsługuje wszystkie żądania. Możemy zatrudnić więcej pracowników, aby poprawić naszą wydajność. Na przykład mam 8 rdzeni i mogę podzielić swój Proces na 8.
Wniosek
Procesy robocze (wątki) mogą pomóc w operacjach JavaScript intensywnie korzystających z procesora. W przeciwieństwie do child_processlub cluster, worker_threadsmoże współdzielić pamięć.
W tym artykule starałem się to ułatwić i wyjaśnić Jak działa worker_threads?
Dziękuje za przeczytanie

![Czym w ogóle jest lista połączona? [Część 1]](https://post.nghiatu.com/assets/images/m/max/724/1*Xokk6XOjWyIGCBujkJsCzQ.jpeg)



































