By WebNest Studio Engineering Team
Java - Core Tutorial
Multitasking vs Multithreading in Java
Multitasking and multithreading both describe doing more than one thing "at once," but they operate at different levels of the operating system, and Java's Thread API specifically targets the second one. Understanding the distinction clarifies why threads are described as "lightweight" compared to processes.
Why it matters
Threads are useful because they share memory, and dangerous for the same reason. This lesson's distinction — separate processes with separate memory versus threads inside one process sharing a heap — explains both why multithreading is fast and why two threads can corrupt each other's data.
Process-Based Multitasking
Process-based multitasking means the operating system runs multiple independent programs (processes) at the same time — for example, a web browser and an IDE running simultaneously on your machine. Each process has its own separate memory space, its own set of system resources, and its own address space that other processes cannot directly access. Communication between processes (inter-process communication) requires explicit mechanisms like sockets, pipes, or files, because processes do not share memory by default. Starting a new process and switching the CPU between processes is relatively expensive for the operating system.
Thread-Based Multitasking (Multithreading)
Thread-based multitasking, or multithreading, means multiple threads run concurrently within a single process. All threads in that process share the same memory space — the same heap, the same static fields, the same open file handles — while each thread still keeps its own call stack and program counter. This shared memory makes communication between threads trivial (they can simply read and write the same objects), but it is also exactly why multithreaded code needs careful synchronization: two threads can otherwise interfere with each other while accessing the same data at the same time.
Why Threads Are Lighter Than Processes
Creating a new process requires the operating system to allocate an entirely new memory space and duplicate a range of OS-level resources, which is comparatively slow and resource-intensive. Creating a new thread within an existing process only requires a new stack and some thread-local bookkeeping, because it reuses the process's existing memory space and resources. This is why thread creation and context switching between threads is considerably cheaper than process creation and context switching, and why a single Java application can comfortably run many threads (for example, one per client connection in a server) but would struggle to spawn a comparable number of separate processes.
Example
Multiple threads within one Java process sharing the same memory (a static counter)
public class MultithreadingDemo {
static int sharedCounter = 0; // shared memory: visible to every thread in this process
public static void main(String[] args) throws InterruptedException {
Runnable incrementTask = () -> {
for (int i = 0; i < 1000; i++) {
synchronized (MultithreadingDemo.class) {
sharedCounter++;
}
}
};
Thread t1 = new Thread(incrementTask, "T1");
Thread t2 = new Thread(incrementTask, "T2");
t1.start();
t2.start();
t1.join();
t2.join();
// Both threads incremented the SAME shared variable -- this is only
// possible because threads of one process share memory.
System.out.println("Final counter value: " + sharedCounter);
}
}
Final counter value: 2000
Common Mistakes
- Using "multitasking" and "multithreading" interchangeably in explanations, when they describe different units of concurrency (processes vs threads).
- Assuming threads in the same process are as isolated as separate processes — they share memory, so unsynchronized access to shared data can cause race conditions.
- Underestimating process creation cost and spawning many separate JVM processes instead of using threads or a thread pool within one process.
- Forgetting that while threads share heap memory, each thread still has its own separate call stack and local variables.
Exercise
Split a sum across two threads. One thread adds the numbers 1 to 100 and the other adds 101 to 200. Each stores its result in its own slot of a shared array, so they never write to the same place. After both finish, print the total.
Expected output: 20100
public class SplitSum {
static int sumRange(int from, int to) {
int sum = 0;
for (int i = from; i <= to; i++) {
sum += i;
}
return sum;
}
public static void main(String[] args) throws InterruptedException {
int[] results = new int[2];
// TODO: thread one stores sumRange(1, 100) in results[0]
// TODO: thread two stores sumRange(101, 200) in results[1]
// TODO: start both, wait for both, then print results[0] + results[1]
}
}
Show hints
- Both threads can see
resultsbecause threads of one process share the heap. - Call
join()on both threads before reading the results.
Show solution
public class SplitSum {
static int sumRange(int from, int to) {
int sum = 0;
for (int i = from; i <= to; i++) {
sum += i;
}
return sum;
}
public static void main(String[] args) throws InterruptedException {
int[] results = new int[2];
Thread first = new Thread(() -> results[0] = sumRange(1, 100));
Thread second = new Thread(() -> results[1] = sumRange(101, 200));
first.start();
second.start();
first.join();
second.join();
System.out.println(results[0] + results[1]); // 20100
}
}
Quick quiz
1. What do the threads of a single process share?
- A. Nothing
- B. Their local variables
- C. Their call stacks
- D. The heap memory
Show answer
D. All threads in a process share the heap, and therefore every object on it.
2. What does each thread have of its own?
- A. Its own call stack
- B. Its own heap
- C. Its own copy of every object
- D. Its own JVM
Show answer
A. Each thread has a private stack holding its method calls and local variables.
3. Which is usually cheaper: switching between two threads of the same process, or between two processes?
- A. Between two processes
- B. Between two threads
- C. They cost the same
- D. It cannot be compared
Show answer
B. Threads share an address space, so a thread switch has less state to save and restore than a process switch.
Interview questions
What is the difference between process-based and thread-based multitasking?
Show answer
Process-based multitasking runs several programs at once, each in its own process with separate memory; communication between them is slow and explicit. Thread-based multitasking runs several tasks inside one program; the threads share memory, so they communicate cheaply through shared objects but must synchronize access to them.
What are the benefits and risks of multithreading?
Show answer
Benefits: better use of multiple processor cores, applications that stay responsive while work continues in the background, and higher throughput on servers. Risks: race conditions when threads modify shared data, deadlocks when they wait on each other's locks, and bugs that depend on timing and are hard to reproduce.
Key Points to Remember
- Process-based multitasking runs multiple independent programs, each with its own isolated memory space.
- Thread-based multitasking (multithreading) runs multiple threads within one process, sharing the same memory space.
- Shared memory makes inter-thread communication easy but requires synchronization to avoid data corruption.
- Threads are more lightweight than processes because they reuse the process's existing memory and resources instead of allocating new ones.
Practice in the playground
Write and run your own code for this topic, or start from the exercise or an example. Runs plain Java 17. Frameworks such as Spring, and databases, are not available here. Your code for each topic is kept in this browser.
Run the examples
Change an input, predict the result, then compare it with the output. Explain why the result changes.
Written by
WebNest Studio Engineering Team
Practical lessons from developers working with Java, Python, React, databases and production systems.
Led by Vansh Duggal, Founder, WebNest Studio · Full-stack & software engineering