Thread pool là một tập worker thread được tạo sẵn và tái sử dụng, thay vì sinh rồi huỷ thread cho từng task — bởi mỗi thread tốn khoảng 1MB stack, tốn thời gian để OS cấp phát, và tốn thêm overhead context switch.
Cách chạy: task queue nhận việc, worker nào rảnh thì lấy task ra chạy rồi quay lại chờ task kế tiếp. ThreadPoolExecutor bên Java, pool worker_threads bên Node.js, worker pattern với goroutine bên Go đều là cách hiện thực ý tưởng này.
Chọn kích thước pool mới là phần khó:
- Task CPU-bound: pool size bằng số CPU core. Thêm thread không giúp gì, chỉ tốn context switch.
- Task I/O-bound: pool lớn hơn số core, vì thread đang chờ I/O có chiếm CPU đâu. Công thức tham khảo: threads = cores * (1 + wait_time / service_time).
Hai thái cực đều dở: pool quá nhỏ thì queue dài và latency cao; pool quá lớn thì tốn bộ nhớ, context switch liên miên và hiệu năng tụt.
Vài con số mặc định để tham khảo: Tomcat để 200, còn I/O thread pool của libuv trong Node.js mặc định chỉ 4 (UV_THREADPOOL_SIZE).