Java Full Course 2026 | Chapter 47: Introduction to Multithreading in Java — Process vs Thread
This chapter introduces the core concepts of multithreading in Java from first principles. It explores the fundamental differences between a program, a process, and a thread, and details how the Operating System (OS) and Java Virtual Machine (JVM) manage memory and execution. Additionally, we examine the mechanics of concurrency, true parallelism, context switching, and the distinction between multitasking and multithreading.
1. Why Do We Need Multithreading?
When developers first encounter Multithreading (executing a program using multiple threads simultaneously), their immediate assumption is that its sole purpose is to make code run faster by reducing execution time.
While performance improvement is a benefit, it is actually one of the least critical advantages of multithreading. The primary goal of multithreading is concurrency and responsiveness—allowing an application to perform multiple operations asynchronously without blocking the user interface or other execution flows.
Real-Life Analogy: The Modern IDE
Consider a modern Integrated Development Environment (IDE) like VS Code or IntelliJ IDEA. As you type code, several operations happen simultaneously:
- Text Editor Thread: Captures your keystrokes and renders characters on the screen.
- Auto-Complete Suggestion Engine: Analyzes your input in the background to suggest keywords (e.g., suggesting
void mainafter you typepublic static). - Background Compiler / Error Checker: Scans your syntax in real-time and draws red squiggly lines under compilation errors.
If your IDE ran on a single thread, it would have to freeze the text editor every time it compiled your code or searched for auto-complete suggestions. Multithreading allows these tasks to be distributed among different threads, running concurrently to provide a seamless user experience.
2. What is a Program?
A Program is a passive entity. It is simply a static set of instructions written in a programming language, stored on a persistent storage device (like a Hard Disk Drive or Solid State Drive).
The Lifecycle of a Java Program on Disk
When you write Java code, it goes through the following static phases:
[Demo.java] (Source Code File on Disk)
|
| Compiled via: javac Demo.java
v
[Demo.class] (Bytecode File on Disk)
At this stage, both Demo.java and Demo.class are merely files sitting on your disk. They consume storage space but do not consume RAM or CPU cycles because they are not actively executing.
3. What is a Process?
A Process is an active entity. It is a program that is currently in execution. When you run a program, the Operating System transitions it from a passive state on the disk to an active state in the main memory (RAM).
Definition: A program that is currently being executed is called a process.
Transition from Program to Process
To run a compiled Java program, you execute the command:
java Demo
When this command is run, the Operating System performs the following actions:
- Allocates a dedicated, isolated memory space within the RAM.
- Loads the compiled bytecode (
Demo.class) from the disk into this allocated RAM space. - Allocates system resources (such as CPU time, file handles, and network sockets) to this execution unit.
This active, isolated execution environment in RAM is called a Process.
4. The Hardware Interaction Model
To understand how processes and threads execute, we must look at how the CPU interacts with the system's memory hierarchy.
Key Hardware Rules:
- CPU-RAM Interaction: The CPU can only execute instructions and process data loaded into the RAM. The CPU never interacts directly with the Hard Disk or SSD during execution.
- Registers: These are ultra-fast, small storage locations built directly inside the CPU. They hold temporary intermediate values during mathematical or logical calculations.
- Process Isolation: Every process is allocated its own private chunk of RAM. For example, if Process 1 (Google Chrome) and Process 2 (VS Code) are running, Chrome cannot access or modify the memory space allocated to VS Code. This memory isolation is strictly enforced by the Operating System for security and stability.
5. What is a Thread?
A Thread is the smallest unit of execution within a process. It is often referred to as a lightweight process.
While a process represents the boundary of allocated resources (like memory), a thread represents the actual path of execution through the code.
Key Characteristics of Threads:
- Existence: A thread cannot exist outside of a process. Every process has at least one active thread.
- The Main Thread: When a Java application starts, the JVM automatically creates a thread named
main. This thread is responsible for executing your program'smain()method line-by-line. - Shared Memory: Unlike processes, which are strictly isolated from one another, threads belonging to the same process share the process's memory space (specifically the Heap and Method Area). This makes communication between threads extremely fast, but it also introduces synchronization challenges.
6. JVM Architecture inside a Process
When you execute java Demo, the Operating System creates a process and boots up the Java Virtual Machine (JVM) inside that process's memory space. The JVM then takes over the responsibility of managing memory and threads.
Shared vs. Private Memory Areas in JVM:
-
Shared Areas (Accessible by all threads in the process):
- Heap Memory: Stores all objects created with the
newkeyword, along with their instance variables. - Method Area: Stores class-level information, method bytecode, class metadata, and static variables.
- Heap Memory: Stores all objects created with the
-
Private Areas (Allocated per individual thread):
- Stack Memory: Every thread gets its own private stack. When a thread calls a method, a new Stack Frame is pushed onto its stack to store local variables and method execution states.
- Program Counter (PC) Register: Each thread has its own PC register to keep track of the address of the JVM instruction currently being executed.
7. Memory Distribution: JVM vs. OS Level
If you study operating systems, you will learn that a process's memory is divided into Code, Data, Heap, Stack, and Registers. However, Java is a platform-independent language. To maintain this independence, the JVM abstracts the underlying OS memory structure into its own memory model.
The table below maps the standard OS-level process memory segments to their corresponding JVM-level abstractions:
8. Step-by-Step Execution Flow of a Java Program
When you run a Java application, a highly coordinated sequence of events occurs between the OS, the JVM, and the CPU:
9. Concurrency vs. Parallelism
Understanding the difference between concurrency and parallelism is vital when working with multithreaded systems.
A. Concurrency (Single-Core CPU)
In a single-core CPU system, only one thread can physically execute at any given millisecond. To run multiple threads, the OS uses Context Switching to rapidly alternate execution between threads.
- How it works: The CPU runs the
mainthread for a tiny fraction of time (e.g., 0.5 seconds), pauses it, runs threadT1for 0.5 seconds, pauses it, and switches back. - The Illusion: Because this switching happens millions of times per second, it creates the illusion that both threads are running simultaneously.
- Definition: Concurrency means making progress on multiple tasks at the same time, even if they are not executing at the exact same physical instant.
B. Parallelism (Multi-Core CPU)
Modern computers feature multi-core processors (e.g., Dual-Core, Quad-Core, Octa-Core). Each core acts as an independent CPU capable of executing its own thread.
- How it works: Core 1 executes the
mainthread while Core 2 simultaneously executes threadT1. - Definition: Parallelism means executing multiple tasks at the exact same physical instant. This is True Parallelism and does not require context switching if the number of active threads is less than or equal to the number of CPU cores.
Comparison Summary:
10. The Mechanics of Context Switching
Context Switching is the process by which the CPU suspends the execution of one thread and resumes the execution of another.
Why is Context Saving Necessary?
Imagine a thread is executing a loop:
for (int i = 0; i < 100; i++) {
// Perform some operations
}
Suppose the CPU executes this loop up to i = 50, and then the OS decides to pause this thread to let another thread run.
When the CPU eventually returns to this thread, it must resume from iteration i = 51, not restart from i = 0. To achieve this, the CPU must save the exact state of the thread before switching away.
Step-by-Step Context Switch Workflow:
Active Thread: Main
|
| 1. OS timer interrupt triggers a context switch
v
| 2. Save current state of Thread Main:
| - Copy Program Counter (PC) address
| - Save intermediate CPU Register values to Thread Main's Stack
v
| 3. Thread Main is paused (moved to Runnable state)
v
| 4. Load state of Thread T1:
| - Retrieve T1's last saved PC address
| - Restore T1's intermediate values into CPU Registers
v
Active Thread: T1 (Resumes execution from its saved PC address)
Note on Performance: Context switching is computationally expensive. Saving registers, updating program counters, and flushing CPU caches takes time. Minimizing unnecessary context switches is a key goal of high-performance concurrent programming.
11. Multitasking vs. Multithreading
While these terms sound similar, they operate at different levels of the system hierarchy.
Key Differences:
- Multitasking: An Operating System-level concept. It allows a user to run multiple independent applications (processes) concurrently (e.g., listening to music on Spotify while writing code in VS Code and browsing the web on Chrome).
- Multithreading: An application-level or programming-level concept. It allows a single application (process) to split itself into multiple concurrent execution paths (threads) to perform sub-tasks.
Tabular Synthesis:
Summary and Key Takeaways
- Programs are passive; Processes are active: A program is a static file on disk (
.class), whereas a process is that program loaded into RAM and executing under OS control. - Threads are lightweight execution units: A process can contain multiple threads. All threads of a process share its Heap and Method Area but maintain private Stacks and Program Counters.
- The JVM manages Java memory: When a Java process starts, the JVM boots inside it and divides the allocated RAM into Heap, Method Area, Thread Stacks, and Program Counters to ensure platform independence.
- Concurrency is not Parallelism: Concurrency is about dealing with lots of things at once (via rapid context switching on a single core). Parallelism is about doing lots of things at once (simultaneously on multiple CPU cores).
- Context Switching saves state: To switch threads, the CPU saves the current thread's Program Counter and register values to its private stack, then loads the saved state of the next thread.
- The CPU only schedules threads: At the hardware level, the CPU does not understand "processes." It only schedules and executes individual threads.
- Multitasking vs. Multithreading: Multitasking runs multiple processes concurrently (managed by the OS), while multithreading runs multiple execution paths within a single process (managed by the JVM/OS).