6.1 Thread Creation, Execution & 6 Lifecycle States
← Back to Chapter 6: Multithreading & Concurrency
A thread is the smallest schedulable execution path managed by the operating system kernel.
1. Process vs Thread
- Process: An isolated execution environment with dedicated address space, file handles, and security context. eg : Spring Boot application or microservice
- Thread: A lightweight execution path inside a process. All threads in a JVM share the same Java Heap Memory, but each thread maintains its own private Thread Stack and Program Counter (PC) Register. eg : HTTP Request, APIs
2. Ways to Define and Launch Threads
2.1. Approach 1: Extending Thread class
// Extending thread
class MyThread extends Thread {
@Override
public void run() {
// run() contains the task executed by this thread.
// We override it because Thread invokes this method when start() is called.
System.out.println("Running in: " + Thread.currentThread().getName());
}
}
2.2. Approach 2: Implementing Runnable (Preferred over extending Thread)
// Implementing Runnable
Runnable task = () -> System.out.println("Running on: " + Thread.currentThread().getName());
Thread t1 = new Thread(task, "Worker-1");
t1.start(); // Spawns an underlying OS thread (never invoke run() directly!)
This approach is preferred over extending Thread class because :
- We cannot extend our class with other classes. As java does not support multiple inheritance
- Allows us to use the benefits of other classes if the task requires composition
- It allows us to write Lambda Expressions because Runnable is a Functional Interface
2.3 Approach 3: Callable<V> with Future<V> (Returns a value, throws checked exceptions)
// Callable<V> with Future<V
Callable<Integer> calcTask = () -> {
Thread.sleep(100);
return 42;
};
3. Daemon vs User Threads
- Daemon Threads: Background threads that run in the background. eg : Garbage Collector, Logging thread
- User Threads: Main threads that run in the foreground. eg : HTTP Request, APIs
4. Runnable, Callable, & Future
Runnable -
- Runnable is an interface used to represent a task that can be executed by a thread.
- Executes a task.
- Does not return a result.
- Cannot directly throw checked exceptions from run().
- Used with Thread or ExecutorService.
Callable -
- Callable is an interface used to represent a task that returns a result after execution.
- Executes a task.
- Returns a result.
- Can throw checked exceptions.
- Generally submitted to an ExecutorService.
Future -
- Future represents the result of an asynchronous computation.
- It is not the task itself. It is an object through which you can :
- Get the result using get()
- Check whether execution is complete using isDone()
- Cancel the task using cancel()
Problem with Future -
it is limited in handling asynchronous operations.
- get() is blocking
- Difficult to chain multiple operations
- Limited exception handling
CompletableFuture was introduced to make asynchronous programming more flexible and composable. It allows you to build non-blocking asynchronous pipelines.
Runnable → "Do this task"
Callable → "Do this task and give me a result"
Future → "I'll give you the result/status of that task later"
5. The 6 JVM Thread Lifecycle States (Thread.State)
┌─────────────────────┐
│ NEW │
│ │
│ Thread object │
│ created, but │
│ not started │
└──────────┬──────────┘
│
start()
│
▼
┌────────────────────────────┐
│ RUNNABLE │
│ │
│ Ready to run / Running │
│ │
│ JVM scheduler decides │
│ when CPU is given │
└───────┬──────┬───────┬─────┘
│ │ │
lock busy │ │ │
┌─────────┘ │ └──────────────┐
▼ │ │
┌─────────────────┐ │ │
│ BLOCKED │ │ │
│ │ │ │
│ Waiting to │ │ │
│ acquire a │ │ │
│ synchronized │ │ │
│ monitor lock │ │ │
└────────┬────────┘ │ │
│ │ │
lock acquired │ │
│ │ │
└───────────────►│ │
│ │
▼ ▼
┌─────────────────┐ ┌─────────────────────┐
│ WAITING │ │ TIMED WAITING │
│ │ │ │
│ Waiting │ │ Waiting for a │
│ indefinitely │ │ specific amount │
│ for another │ │ of time │
│ thread │ │ │
└────────┬────────┘ └──────────┬──────────┘
│ │
notification / time expires /
interrupt / signal interrupt
│ │
└───────────┬────────────┘
│
▼
RUNNABLE
│
│
run() completes
│
▼
┌──────────────────┐
│ TERMINATED │
│ │
│ Thread execution │
│ has finished │
└──────────────────┘
NEW: Created vianew Thread(), butstart()has not been invoked.RUNNABLE: Ready for CPU scheduling or actively executing bytecode in the JVM.BLOCKED: Waiting to acquire an intrinsic monitor lock (synchronized) currently held by another thread.WAITING: Indefinitely waiting for another thread to perform an action (Object.wait(),Thread.join(),LockSupport.park()).TIMED_WAITING: Waiting with a specified timeout (Thread.sleep(ms),Object.wait(timeout)).TERMINATED: Execution ofrun()completed normally or threw an uncaught exception.