[!NOTE] Historically, your Java program executed on a single "Main Thread". It processed line 1, then line 2. If line 2 was a 10-second database query, the application froze for 10 seconds before hitting line 3.
To build high-performance web servers (which handle 10,000 user requests simultaneously), we must execute code Concurrently across multiple CPU threads.
The Physical Thread Array
When a user runs a Java program, the JVM spawns an independent "Main Thread".
You can spawn your own background threads by:
- Creating a class that implements the
Runnableinterface. - Writing the heavy logic inside the
run()method. - Handing that object to a raw
Threadobject and executing.start().
// 1. Build the heavy background task logic
class HeavyTask implements Runnable {
public void run() {
System.out.println("Beginning huge 10-second data processing on Thread: " + Thread.currentThread().getName());
// ... intensive CPU math ...
}
}
public class Main {
public static void main(String[] args) {
System.out.println("Main Application Booting Up...");
// 2. Instantiate and hook it into a physical Thread!
Thread myWorkerThread = new Thread(new HeavyTask());
// 3. START IT! This instantly detaches vertically from the main thread!
myWorkerThread.start();
System.out.println("Main application continues immediately without waiting!");
}
}
Thread Pools & The ExecutorService
Raw threading is extremely dangerous. Spinning up millions of threads (e.g., one per user click) will crash the entire operating system, as threads inherently consume RAM.
Modern Java developers almost never use new Thread(). They use an ExecutorService (a Thread Pool).
You tell the system: "I'm giving you a pool of exactly 10 threads. Here are 5,000 tasks. Recycle those 10 threads to churn through the block."
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ThreadPoolExample {
public static void main(String[] args) {
// 1. Request a fixed squad of 5 heavily optimized worker threads
ExecutorService pool = Executors.newFixedThreadPool(5);
// 2. Submit 100 heavy jobs to the squad. They will balance the work perfectly!
for (int i = 0; i < 100; i++) {
pool.submit(new HeavyTask());
}
// 3. Order the pool to shutdown gracefully after the last job finishes.
pool.shutdown();
}
}
[!CAUTION] Race Conditions: If Thread A and Thread B try to update the exact same
int bankBalance = 100at the precise exact millisecond, they interfere and overwrite each other, causing money to vanish! You must use thesynchronizedkeyword orAtomicIntegervariables to lock memory addresses from being concurrently touched by competing threads.