← Назад к вопросам

Что такое ThreadPool?

2.3 Middle🔥 181 комментариев
#Node.js и JavaScript#Архитектура и паттерны

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI30 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

ThreadPool — пул потоков для параллельной обработки

ThreadPool (пул потоков) — это механизм управления потоками, который позволяет эффективно распределять работу между потоками.

Концепция ThreadPool

Без ThreadPool:
Каждая задача → новый поток → много overhead

С ThreadPool:
Все задачи → одна очередь → несколько переиспользуемых потоков

ThreadPool в Node.js (Worker Threads)

Node.js работает в одном потоке, но для CPU-intensive задач можно использовать Worker Threads.

Проблема:

const crypto = require('crypto');

function heavyComputation(data) {
  // Это блокирует event loop!
  return crypto.pbkdf2Sync(data, 'salt', 100000, 64, 'sha512');
}

app.post('/compute', (req, res) => {
  const result = heavyComputation(req.body.data);
  res.json({ result }); // Ответ задерживается!
});

Тяжёлое вычисление блокирует event loop, все остальные запросы ждут.

Решение: Worker Pool

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

class WorkerPool {
  constructor(workerScript, poolSize = 4) {
    this.workers = [];
    this.taskQueue = [];
    this.activeWorkers = new Set();
    
    for (let i = 0; i < poolSize; i++) {
      this.workers.push(this.createWorker(workerScript));
    }
  }
  
  createWorker(workerScript) {
    const worker = new Worker(workerScript);
    
    worker.on('message', (result) => {
      this.activeWorkers.delete(worker);
      
      if (this.taskQueue.length > 0) {
        const { data, resolve } = this.taskQueue.shift();
        this.executeTask(worker, data, resolve);
      }
    });
    
    return worker;
  }
  
  executeTask(worker, data, resolve) {
    this.activeWorkers.add(worker);
    worker.once('message', (result) => {
      resolve(result);
    });
    worker.postMessage(data);
  }
  
  async run(data) {
    return new Promise((resolve) => {
      const freeWorker = this.workers.find(
        w => !this.activeWorkers.has(w)
      );
      
      if (freeWorker) {
        this.executeTask(freeWorker, data, resolve);
      } else {
        this.taskQueue.push({ data, resolve });
      }
    });
  }
  
  terminate() {
    this.workers.forEach(w => w.terminate());
  }
}

const pool = new WorkerPool(path.join(__dirname, 'worker.js'), 4);

app.post('/compute', async (req, res) => {
  const result = await pool.run(req.body.data);
  res.json(result);
});

ThreadPool в других контекстах

Connection Pool (БД):

const pg = require('pg');

const pool = new pg.Pool({
  max: 20,  // Максимум подключений
  min: 5,   // Минимум готовых
  connectionTimeoutMillis: 2000,
  idleTimeoutMillis: 30000
});

app.get('/users', async (req, res) => {
  // Используем существующее подключение
  const result = await pool.query('SELECT * FROM users');
  res.json(result.rows);
});

Job Queue (фоновые задачи):

const Bull = require('bull');

const jobQueue = new Bull('email-queue');

// 4 рабочих обрабатывают параллельно
jobQueue.process(4, async (job) => {
  await sendEmail(job.data.email, job.data.subject);
  return { success: true };
});

app.post('/send-email', async (req, res) => {
  const job = await jobQueue.add(
    { email: req.body.email, subject: 'Hello' },
    { attempts: 3 }
  );
  res.json({ jobId: job.id });
});

Сравнение подходов

ПодходПлюсыМинусыКогда
Single ThreadПростоМедленноI/O операции
Worker PoolПараллелизмOverhead памятиCPU-intensive
Connection PoolЭффективноСложнееБД операции
Job QueueАсинхронноОтдельный сервисФоновые задачи

Best Practices

// 1. Размер пула = CPU ядра для CPU-intensive
const os = require('os');
const poolSize = os.cpus().length;

// 2. Для I/O пул может быть больше
const ioPoolSize = 20;

// 3. Graceful shutdown
process.on('SIGTERM', async () => {
  pool.terminate();
  process.exit(0);
});

Key takeaway

  • ThreadPool = управление потоками через очередь
  • В Node.js для CPU-intensive используй Worker Threads
  • Для I/O используй Connection Pools или Job Queues
  • Размер пула влияет на производительность
  • Обрабатывай graceful shutdown
Что такое ThreadPool? | PrepBro