Threads - our industrious little helpers in the background. 🚀 In the world of modern applications, where speed, responsiveness and parallelism matter, threads are becoming an indispensable tool. But, is it possible to create an infinite number of them? 🤔 Where does the limit lie?
In this article we will answer the questions:
A thread is a unit of execution within a process. It shares the process’s address space and resources with other threads. 🧬 We can think of it as an employee inside a company — it can run independently, but still shares resources with others.
Yes, and it's huge! 🧠💥
Each CPU core can physically execute one thread at a time (and sometimes more, with Hyper-Threading support). The more cores, the more actual parallel processing.
Device | Number of cores | Hardware threads (logical processors) |
---|---|---|
Old smartphone | 4 | 4 hardware threads (no SMT on most mobile SoCs) |
MacBook M4 Pro | 12 or 14 | 12 or 14 hardware threads (no Hyper-Threading/SMT) |
Server x64 | 32+ | 32 hardware threads (no SMT) or 64+ with SMT |
🔎 With 1000 threads on an 8-core CPU, the system has to context switch — which slows everything down.
More threads than cores → the OS scheduler performs frequent context switches between runnable threads, which adds overhead and can hurt performance.
Example: even on a laptop with 8 hardware threads, you can start 10,000+ OS threads — most will be sleeping or waiting.
✅ Yes, because:
📦 In a nutshell:
#include <thread>
#include <iostream>
int main() {
std::cout << "Available CPU cores:"
<< std::thread::hardware_concurrency() << std::endl;
// hint, not a guarantee
}
std::thread
: default ~2 MiB on Tier-1 platforms (configurable via Builder::stack_size
).
-Xss
, scheduler policies).
asyncio
for I/O-bound tasks or
multiprocessing
for CPU-bound work.
std::thread
spawns OS threads with a ~2 MiB default stack on Tier-1
platforms. You can reduce it with std::thread::Builder::stack_size(...)
, but test carefully.
For massive concurrency, prefer an async runtime (e.g., Tokio).
public class ThreadExplosion {
public static void main(String[] args) {
int count = 0;
try {
while (true) {
new Thread(() -> {
try { Thread.sleep(Long.MAX_VALUE); } catch (InterruptedException e) {}
}).start();
count++;
if (count % 100 == 0)
System.out.println("Threads: " + count);
}
} catch (OutOfMemoryError e) {
System.out.println("Thread limit reached: " + count);
}
}
}
🧭 Tip: if you truly need many platform threads on the JVM, consider lowering per-thread stack size with -Xss
(trade-off: less stack headroom).
🚨 Note: You may lock up your computer, so test this only at your own risk! 😉
Language | Typical limits (very OS/stack-dependent) | Asynchronous / lightweight alternatives |
---|---|---|
Java | Thousands of platform threads typical; depends on -Xss and OS limits. |
Virtual Threads (Loom) |
Kotlin | Same platform thread limits as Java. | Coroutines |
Python | OS/stack-dependent; GIL blocks CPU-parallelism in one process. | asyncio , multiprocessing |
Rust | OS threads with sizable default stacks; not ideal for “10k+” without tuning. | Tokio (async runtime) |
C/C++ | Feasible count varies with per-thread stacks and OS limits. | Boost::asio, manual management |
JavaScript | 1 main thread (+ libuv pool); CPU-bound work via Worker Threads. | async/await, Web Workers |