ExecutorService (Java 5+) quản lý thread pool — bạn submit Runnable/Callable, executor lo phần còn lại.
new Thread() thủ công burst 10K request → 10K OS thread → OOM. Không reuse, không backpressure.
java
ExecutorService exec = Executors.newFixedThreadPool(10);
exec.execute(() -> handle(request)); // Runnable
Future<String> f = exec.submit(() -> fetch()); // Callable → Future<T>
exec.shutdown();
if (!exec.awaitTermination(30, TimeUnit.SECONDS)) exec.shutdownNow();Factory trong Executors:
| Factory | Khi dùng |
|---|---|
newFixedThreadPool(n) | CPU-bound |
newCachedThreadPool() | Task ngắn, ít — nguy hiểm nếu burst (unbounded) |
newScheduledThreadPool(n) | Task định kỳ/delay |
newVirtualThreadPerTaskExecutor() (Java 21+) | I/O-bound — RECOMMENDED 2026 |
Sizing: CPU-bound = số core; I/O-bound truyền thống = cores × (1 + wait/compute); Java 21+ → Virtual Threads.
Sai lầm hay gặp: không shutdown (leak), newCachedThreadPool() không giới hạn (OOM), default queue unbounded, nuốt exception trong task không log.
Java 21+ pattern:
java
try (var exec = Executors.newVirtualThreadPerTaskExecutor()) {
// auto-shutdown khi try kết thúc
}Đừng new Thread() thủ công trong production.
Virtual Threads là chuẩn mới cho I/O workload.