Concorrência e Multithreading em JavaScript: Guia Completo

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course

Concorrência e Multithreading em JavaScript: como fazer o código rodar mais rápido



JavaScript historicamente foi uma linguagem single-thread, mas isso não significa que ela não pode processar várias tarefas simultaneamente. No Node.js moderno e nos navegadores, existem mecanismos poderosos para trabalhar com concorrência e multithreading. Compreender esses conceitos é criticamente importante para criar aplicações server-side e client-side de alto desempenho.



Neste artigo, vamos entender a diferença entre concorrência e paralelismo, como funciona o Event Loop, quando usar Worker Threads e Web Workers, além de analisar exemplos práticos em Node.js.



1. Event Loop e I/O não bloqueante



A base da concorrência em JavaScript é o Event Loop (loop de eventos). Este é um mecanismo que permite executar operações assíncronas (por exemplo, leitura de arquivos, requisições ao banco de dados) sem bloquear a thread principal.



Imagine uma fila: o Event Loop pega uma tarefa da fila (call stack), a executa e, se encontrar uma operação assíncrona (como setTimeout ou fetch), a transfere para a Web API (no navegador) ou libuv (no Node.js). Após a conclusão da operação, seu callback vai para a fila de tarefas (task queue). O Event Loop verifica constantemente se a pilha não está vazia e, se estiver vazia, pega a próxima tarefa da fila.



Exemplo de código assíncrono:



const fs = require('fs');

console.log('Início');

fs.readFile('example.txt', 'utf8', (err, data) => { if (err) throw err; console.log('Arquivo lido:', data);});

console.log('Fim');

// Saída:// Início// Fim// Arquivo lido: ...


Observe: console.log('Fim') é executado antes da leitura do arquivo. Isso é I/O não bloqueante — a thread principal não espera a conclusão da operação, mas continua a execução.



2. Web Workers e Worker Threads: verdadeiro multithreading



Embora o Event Loop lide bem com operações de I/O, ele não ajuda na execução de cálculos "pesados" (processamento de imagens, criptografia, ordenações complexas). Se você executar esse tipo de código na thread principal, toda a interface (ou servidor) "congelará" até a conclusão do cálculo.



Para resolver esse problema, existem os Web Workers (no navegador) e Worker Threads (no Node.js). Eles permitem executar código JavaScript em threads separadas do sistema operacional.



Exemplo com Worker Threads no Node.js



Vamos criar o arquivo worker.js:



const { parentPort } = require('worker_threads');

// Tarefa pesada: calcular a soma dos númeroslet sum = 0;for (let i = 0; i < 1e9; i++) { sum += i;}

// Envia o resultado de volta para a thread principalparentPort.postMessage(sum);


Arquivo principal main.js:



const { Worker } = require('worker_threads');

console.log('Thread principal: iniciando worker');

const worker = new Worker('./worker.js');

worker.on('message', (result) => { console.log('Resultado do worker:', result);});

worker.on('error', (err) => { console.error('Erro no worker:', err);});

worker.on('exit', (code) => { if (code !== 0) { console.error(`Worker encerrado com código ${code}`); }});

console.log('Thread principal: continuando trabalho...');

// Saída:// Thread principal: iniciando worker// Thread principal: continuando trabalho...// Resultado do worker: 499999999500000000


Como você pode ver, a thread principal não é bloqueada, e o worker executa os cálculos em segundo plano. Isso é o verdadeiro multithreading.



3. Async/Await e Promise: gerenciamento de concorrência



O JavaScript moderno oferece maneiras elegantes de trabalhar com código assíncrono — async/await e Promise. Eles não criam novas threads, m

Blogs

Book Recommendations