Introduction
Multithreading is one of the most important concepts in modern programming. It allows a program to execute multiple tasks concurrently, improving responsiveness and performance.
However, a thread does not start running immediately after it is created. Like a human being, a thread goes through different stages during its existence. These stages collectively form the Thread Lifecycle.
Python provides the threading module to create and manage threads. Each thread moves through several states from creation to termination.
What is Python Thread Lifecycle?
The Thread Lifecycle refers to the sequence of states that a thread passes through during its execution.
A thread does not remain active throughout the program. Instead, it transitions through different stages such as creation, execution, waiting, and termination.
The lifecycle helps the operating system and Python interpreter manage thread execution efficiently.
Thread Lifecycle States
A Python thread generally passes through the following states:
New
↓
Runnable
↓
Running
↓
Waiting / Blocked
↓
Terminated
Each state represents a different phase of thread execution.
Thread Lifecycle Diagram
+-------+
| New |
+-------+
|
v
+----------+
| Runnable |
+----------+
|
v
+---------+
| Running |
+---------+
|
v
+------------------+
| Waiting/Blocked |
+------------------+
|
v
+------------+
| Terminated |
+------------+
Let’s examine each state in detail.
1. New State
The New State is the first stage in a thread’s lifecycle.
A thread enters this state when it is created but not yet started.
Example:
import threading
def task():
print("Task Running")
thread = threading.Thread(
target=task
)
At this point:
Thread Created
Thread Not Started
The thread object exists in memory but has not begun execution.
Characteristics of New State
- Thread object is created.
- Memory is allocated.
- Thread has not started execution.
- start() method has not been called.
2. Runnable State
The thread enters the Runnable State after the start() method is called.
Example:
thread.start()
Now Thread Ready To Run.
The thread is waiting for CPU allocation.
The operating system scheduler decides when the thread gets CPU time.
Characteristics of Runnable State
- Thread is ready for execution.
- Waiting for CPU resources.
- Can move to Running state anytime.
Example of Runnable State
import threading
def task():
print("Task Started")
thread = threading.Thread(
target=task
)
thread.start()
After start() is executed, the thread becomes runnable.
3. Running State
A thread enters the Running State when the CPU assigns execution time.
At this stage:
Thread Actively Executing
Example:
import threading
def task():
print("Thread Running")
thread = threading.Thread(
target=task
)
thread.start()
Output:
The thread executes the target function.
Characteristics of Running State
- Thread actively executes instructions.
- CPU resources are allocated.
- Can move to Waiting state.
- Can move to Terminated state after completion.
Example with Multiple Threads
import threading
def task():
print(
threading.current_thread().name
)
for i in range(3):
thread = threading.Thread(
target=task
)
thread.start()
Output:
Thread-2
Thread-3
Each thread enters the running state when scheduled by the CPU.
4. Waiting State
Sometimes a thread cannot continue execution immediately.
It enters the Waiting State (also called Blocked State).
Example situations:
- Waiting for user input
- Waiting for file access
- Waiting for network response
- Waiting for another thread
- Waiting for a lock
Example Using sleep()
import threading
import time
def task():
print("Started")
time.sleep("3")
print("Finished")
thread = threading.Thread(
target=task
)
thread.start()
During:
time.sleep("3")
The thread enters the waiting state.
Characteristics of Waiting State
- Thread temporarily pauses execution.
- CPU resources are released.
- Thread resumes when waiting condition is removed.
Waiting Due to join()
Example:
import threading
import time
def task():
time.sleep("2")
print("Task Completed")
thread = threading.Thread(
target=task
)
thread.start()
thread.join()
print("Program Ended")
The main thread waits until the child thread finishes.
Waiting Due to Lock
Example:
import threading
lock = threading.Lock()
def task():
with lock:
print("Working")
If another thread already holds the lock, Current Thread Waits Until the lock becomes available.
5. Terminated State
The Terminated State is the final stage of the thread lifecycle.
A thread enters this state when:
- Its task completes successfully.
- An exception occurs.
- The program ends.
Example:
def task():
print("Done")
thread = threading.Thread(
target=task
)
thread.start()
thread.join()
After execution, Thread Terminated. The thread cannot restart.
Characteristics of Terminated State
- Thread execution is complete.
- Resources are released.
- Cannot be started again.
Checking Thread Status
Python provides is_alive().
Example:
import threading
import time
def task():
time.sleep("2")
thread = threading.Thread(
target=task
)
thread.start()
print(
thread.is_alive()
)
Output:
After completion:
Complete Thread Lifecycle Example
import threading
import time
def task():
print("Running")
time.sleep("2")
print("Finished")
thread = threading.Thread(
target=task
)
print("New State")
thread.start()
print("Runnable/Running State")
thread.join()
print("Terminated State")
Output:
Runnable/Running State
Running
Finished
Terminated State
Real-Life Examples:
1. File Download Manager
Consider a download application.
New State
User clicks download.
Runnable State
Download thread created.
Running State
File starts downloading.
Waiting State
Network temporarily unavailable.
Terminated State
Download completed.
2. Online Chat Application
Thread lifecycle:
New
Message listener thread created.
Runnable
Thread waits for CPU.
Running
Thread receives messages.
Waiting
Waits for incoming messages.
Terminated
Application closes.
Web Scraping
Multiple scraping threads:
import threading
def scrape(url):
print(
f"Scraping {url}"
)
thread = threading.Thread(
target=scrape,
args=("example.com",)
)
thread.start()
Lifecycle:
Create
Ready
Run
Wait For Response
Finish
Thread Lifecycle vs Process Lifecycle
| Feature | Thread Lifecycle | Process Lifecycle |
|---|---|---|
| Unit | Thread | Process |
| Memory | Shared | Separate |
| Creation Time | Fast | Slower |
| Resource Usage | Low | High |
| Communication | Easy | Complex |
Common Mistakes
1. Forgetting start()
Incorrect:
thread = threading.Thread(
target=task
)
The thread remains in the New State.
Correct:
thread.start()
2. Trying to Restart a Thread
Incorrect:
thread.start()
thread.start()
Output:
A terminated thread cannot be restarted.
3. Ignoring join()
Without:
thread.join()
The main program may finish before threads complete.
4. Creating Too Many Threads
Excessive threads can reduce performance.
Use threads only when necessary.
5. Ignoring Synchronization
Shared resources can cause race conditions.
Use:
threading.Lock()
Conclusion
The Python Thread Lifecycle describes the journey of a thread from creation to termination. Every thread passes through states such as New, Runnable, Running, Waiting, and Terminated. Understanding these states helps developers build efficient multithreaded applications, avoid synchronization issues, and improve program performance.
By mastering thread creation, execution control, waiting mechanisms, and lifecycle management, you can effectively use Python threads in real-world applications such as web scraping, chat systems, download managers, and background processing tasks.