The optimal thread pool size depends on several factors, mainly the type of tasks your application runs and the hardware it runs on.
✅ General Formula (CPU-bound tasks):
For tasks that heavily use the CPU (e.g., calculations, compression):
Number of threads ≈ Number of CPU cores + 1
This avoids excessive context switching and keeps all cores busy.
✅ Formula for I/O-bound tasks:
If your tasks spend a lot of time waiting (e.g., network calls, disk access):
Number of threads ≈ Number of cores * (1 + Wait time / Compute time)
This formula comes from the “thread pool sizing” model by Brian Goetz.
Example:
If tasks spend 80% of the time waiting and 20% computing:
Threads ≈ Cores * (1 + 0.8 / 0.2) = Cores * 5
🧪 Empirical Tuning (Best Practice)
- Measure actual performance with different sizes.
- Use profilers or thread dump analysis.
- Watch out for:
- Too few threads: Underutilization, idle CPU
- Too many threads: CPU thrashing, memory pressure, context-switching overhead
🛠️ In Java (Example)
int cores = Runtime.getRuntime().availableProcessors();
ExecutorService pool = Executors.newFixedThreadPool(cores + 1);
💡Pro Tip:
Use ThreadPoolExecutor
instead of Executors.newFixedThreadPool()
when you want full control over:
- core and max pool size
- queue type and size
- rejection policy