Python

P
PythonHub
Progress 0%

Python

  • Home
  • History of Python
  • Applications of Python
  • Introduction To Python
    • What is Python
    • Character Set
    • Tokens in Python
    • Python Execution Mode
    • Variable And Identifiers
    • Data Types in Python
    • Operators And Expressions
    • Constants in Python
    • Assignment Statement
    • Input / Output in Python
    • Simple Python Scripts
    • Namespace in Python
    • πŸ“ Assignments
  • Operators in Python
    • Arithmetic Operators
    • Assignment Operators
    • Shorthand Assignment Operators
    • Relational Operators
    • Logical Operators
    • Bitwise Operators
    • Special Operators
    • πŸ“ Assignments
  • Input Output in Python
    • Accept Input
    • Output Formatting
    • πŸ“ Assignments
  • Conditional Statement
    • Decision Making
    • if Statement
    • IF-ELSE STATEMENT
    • IF-ELSE LADDER
    • NESTED IF-ELSE
    • Short Hand IF-ELSE
    • πŸ“ Assignments
  • Loops
    • Introduction to Loops
    • While Loop
    • Nested While Loop
    • πŸ“ While Loop Assignments
    • For Loop
    • For Loop Examples
    • Nested For Loop
    • Nested For Loop Examples
    • Infinite While Loops
    • Infinite For Loops
    • Break, Continue and Else in Loops
    • Difference Between For and While Loop
    • For Each Loop
    • πŸ“ For Each Assignments
    • πŸ“ All Loops Assignments
  • List
    • List in Python
    • Access List Elements
    • List Functions
    • Iterate (Loop) List
    • List Comprehension
    • πŸ“ Assignments
  • Tuple
    • Tuple in Python
    • Access Tuple Elements
    • Tuple Functions
    • Iterate (Loop) Tuple
    • Unpack Tuple
    • Tuple Comprehension
    • πŸ“ Assignments
  • Set
    • Set in Python
    • Access Set Elements
    • Set Methods
    • Iterate (Loop) Set
    • Pack/Unpack Set
    • Set Comprehension
    • πŸ“ Assignments
  • Dictionary
    • Dictionary
    • Access Dictionary Items
    • Dictionary Methods
    • Iterate (Loop) Dictionary
    • Formatting Dictionaries
    • Nested Dictionaries
    • Dictionary Comprehension
    • πŸ“ Assignments
  • Diff List Tuple Set Dictionary
    • List vs Tuple
    • List vs Set
    • List vs Dictionary
    • Tuple vs Set
    • Tuple vs Dictionary
    • Dictionary vs Set
    • πŸ“ Assignments
  • Exception
    • Error vs Exception
    • Types of Exception
    • Exception Handling
    • User Defined Exception
    • Logging Exception
    • πŸ“ Assignments
  • Functions
    • Introduction to Functions
    • Modular Programming
    • Types of Functions
    • Inbuilt Functions
    • Need For User-Defined Function
    • Elements of User Defined Function
    • Function Arguments
    • Nesting of Functions
    • Recursion
    • Global Local and Non Local
    • Python Lambda Functions
    • πŸ“ Assignments
  • Python Module
    • Introduction to Module
    • Inbuilt Modules in Python
    • User Defined Module
    • πŸ“ Assignments
  • File Handling
    • Introduction to Files
    • Create File
    • Read Files
    • Write to File
    • Rename File
    • Copy File
    • Move File
    • List Files in Directory
    • Binary Files
    • Zipping and Unzipping Files
    • πŸ“ Assignments
  • Strings
    • Basics of Strings
    • String Special Operators
    • String Formatting Operators
    • String Methods
    • πŸ“ Assignments
  • Regular Expressions
  • Python OOPS
    • Basics of Object Oriented
    • What are Classes and Objects?
    • Creating Class and Object
    • OOP vs Procedural Programming
    • Difference Between Classes and Objects
    • Constructors
    • Destructor
    • Built Class Methods and Attributes
    • Class and Instance Variables
    • Inheritance in Python
    • Single Inheritance
    • Multiple Inheritance
    • Multilevel Inheritance
    • Hierarchical Inheritance
    • Hybrid Inheritance
    • Abstraction
    • Method Overriding
    • Abstract Method
    • Interfaces in Python
    • Abstract Class vs Interface
    • Public, Private and Protected
    • Overloading vs Overriding
    • Inheritance vs Composition
    • Encapsulation
    • Polymorphism
    • Inner Classes
    • πŸ“ Assignments
  • Advanced Python
    • Iterator in Python
    • Generator in Python
    • Decorator in Python
    • Type Hints in Python
    • Async/Await Programming
    • Dataclasses in Python
    • Context Managers in Python
    • Property Decorator in Python
    • __slots__ in Python
    • Enums in Python
    • Walrus Operator in Python
    • Match-Case in Python
    • πŸ“ Assignments
  • Python Standard Library
    • Collections Module
    • Itertools Module
    • Functools Module
    • Datetime Module
    • JSON Module
    • OS Module
    • Sys Module
    • Random Module
    • Math Module
    • πŸ“ Assignments
  • Python Testing
    • Unit Testing in Python
    • Pytest Framework
    • Mocking in Python
    • πŸ“ Assignments
  • Python Best Practices
    • PEP 8 Style Guide
    • Docstrings in Python
    • Logging in Python
    • Code Optimization Tips
    • Debugging Techniques
    • πŸ“ Assignments
  • MySQL Database in Python
    • Introduction to MySQL with Python
    • DBMS vs File System
    • Connecting to MySQL Database
    • Create Database in MySQL
    • Create Table in MySQL
    • Insert Data in MySQL
    • Insert Multiple Rows
    • Select Data from MySQL
    • WHERE Clause in MySQL
    • Update Data in MySQL
    • Delete Data from MySQL
    • Parameterized Queries
    • Transaction Management
    • Error Handling
    • Connection Pooling
    • MySQL Drivers Guide
    • Joins in MySQL
    • Aggregation Functions
    • Backup MySQL Database
    • Best Practices
    • πŸ“ Assignments
  • MySQL Database Operations
    • SELECT Statement
    • MySQL Operators
    • DDL Statements
    • DML Statements
    • Subqueries
    • JOIN Operations
    • Aggregation
    • Case Study
    • πŸ“ Assignments
  • Graphics in Python
  • Threads in Python
    • Introduction to Threads
    • Process vs Threads
    • Concurrent Programming & GIL
    • Uses of Threads
    • Creating Threads
    • Single Tasking
    • Multi Tasking
    • Thread Synchronization
    • πŸ“ Assignments
  • Interview Questions & Answers
  • Python Case Studies
  • Multiple Choice Questions
  • πŸ“ Practice Problems
Get in Touch
  • tech2dsm@gmail.com

© Sankalan Data Tech

Python Language Interactive Tutorial

Python: Introduction to Threads

Python Threads - Complete Guide

Learn what threads are and how to use them in Python.

Created by Sankalan Data Tech Team Verified
Data Engineers, Analysts, Scientists & Trainers
Created by experienced Python developers, data engineers, and data scientists to make programming easy through practical examples, real-world experience, and clear explanations.
Read Time: 10 minutes Level: Intermediate Topic: Python Threads Prerequisite: Functions, Loops
On this page:
  • What is a Thread?
  • Why Use Threads?
  • The threading Module
  • Creating Threads
  • Joining Threads
  • Daemon Threads
  • Real-World Example
  • Best Practices
  • Try It Yourself
  • Quiz
  • FAQ
Share this tutorial:
Twitter LinkedIn Facebook WhatsApp Reddit Telegram Email Copy Link
What You'll Learn Here
  • What is a thread β€” understanding the concept
  • Why use threads β€” benefits and use cases
  • Creating threads β€” using the threading module
  • Joining threads β€” waiting for threads to finish
  • Daemon threads β€” background tasks
  • Real-world examples β€” practical applications

What is a Thread?

A thread is a separate flow of execution within a program. Think of it like a worker who can do one task at a time. When you have multiple threads, it's like having multiple workers who can work on different tasks simultaneously.

🍳 Think of it like cooking in a kitchen.

Imagine you're cooking a meal. You could chop vegetables, then boil pasta, then prepare the sauce one after another. That's like a single-threaded program.

But if you have a helper, one person can chop vegetables while the other boils pasta. Both tasks happen at the same time. That's like multi-threading!

Single Thread

One task at a time, sequential execution

Multiple Threads

Multiple tasks running simultaneously

Thread Safety

Managing shared data between threads

πŸ’‘ Key concept: A program is like a process. A thread is a lightweight unit of execution within that process. Multiple threads share the same memory space.

1

Thread vs Process

# ============================================================
# THREAD VS PROCESS
# ============================================================

print("""
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                         PROCESS                                β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚
β”‚  β”‚                     MEMORY SPACE                        β”‚  β”‚
β”‚  β”‚  β”Œβ”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”                            β”‚  β”‚
β”‚  β”‚  β”‚Threadβ”‚  β”‚Threadβ”‚  β”‚Threadβ”‚   <-- Multiple threads   β”‚  β”‚
β”‚  β”‚  β”‚  1   β”‚  β”‚  2   β”‚  β”‚  3   β”‚    share memory          β”‚  β”‚
β”‚  β”‚  β””β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”˜                            β”‚  β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Key Differences:
- Processes have separate memory space
- Threads share memory space (more efficient)
- Processes are heavier (more resources)
- Threads are lightweight
- Processes are isolated; threads communicate easily
""")

Key point: Threads are lightweight and share memory, making them efficient for tasks that need to communicate.

Quick Check: What is a thread? (Answer: A separate flow of execution within a program)

Why Use Threads?

2

Benefits of Using Threads

# ============================================================
# WHY USE THREADS?
# ============================================================

print("""
1. IMPROVED PERFORMANCE
   - Multiple tasks run simultaneously
   - Better CPU utilization
   - Faster execution for I/O-bound tasks

2. BETTER RESPONSIVENESS
   - UI remains responsive while processing
   - No "freezing" in applications

3. RESOURCE EFFICIENCY
   - Threads share memory
   - Less overhead than processes

4. SIMPLER PROGRAMMING
   - Natural way to handle concurrent tasks
   - Cleaner code structure

5. REAL-WORLD APPLICATIONS
   - Web servers handling multiple requests
   - Download managers downloading multiple files
   - GUI applications processing background tasks
""")

# ============================================================
# COMMON USE CASES
# ============================================================

print("""
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Use Case                    β”‚ Why Threads Help                   β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ Web Scraping                β”‚ Fetch multiple pages at once       β”‚
β”‚ File Processing             β”‚ Process multiple files in parallel β”‚
β”‚ Database Operations         β”‚ Run multiple queries concurrently  β”‚
β”‚ GUI Applications            β”‚ Keep UI responsive                 β”‚
β”‚ API Calls                   β”‚ Make multiple API calls at once    β”‚
β”‚ Download Managers           β”‚ Download multiple files at once    β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
""")

Key point: Threads help you do multiple things at once, making your program faster and more responsive.

Quick Check: Why would you use threads in a GUI application? (Answer: To keep the UI responsive while performing background tasks)

The threading Module

3

Introduction to Python's threading Module

Python's threading module provides a way to create and manage threads. It's built into Python, so you don't need to install anything.

# ============================================================
# BASIC THREADING
# ============================================================

import threading
import time

# ============================================================
# 1. SIMPLE THREAD EXAMPLE
# ============================================================

def print_numbers():
    """Print numbers from 1 to 5"""
    for i in range(1, 6):
        print(f"Number: {i}")
        time.sleep(0.5)

def print_letters():
    """Print letters from A to E"""
    for letter in ['A', 'B', 'C', 'D', 'E']:
        print(f"Letter: {letter}")
        time.sleep(0.5)

# Create threads
thread1 = threading.Thread(target=print_numbers)
thread2 = threading.Thread(target=print_letters)

# Start threads
thread1.start()
thread2.start()

# Wait for threads to finish
thread1.join()
thread2.join()

print("Both threads finished!")

# ============================================================
# 2. THREAD WITH ARGUMENTS
# ============================================================

def greet(name, times):
    """Greet a person multiple times"""
    for i in range(times):
        print(f"Hello, {name}! (Greeting {i+1})")
        time.sleep(0.3)

thread = threading.Thread(target=greet, args=("Alice", 3))
thread.start()
thread.join()

# ============================================================
# 3. THREAD COUNT
# ============================================================

print(f"Active threads: {threading.active_count()}")
print(f"Current thread: {threading.current_thread().name}")

threading module key points:

  • Thread(target=function) β€” creates a thread
  • start() β€” starts the thread
  • join() β€” waits for the thread to finish
  • active_count() β€” number of active threads
  • current_thread() β€” information about current thread

Quick Check: What method starts a thread? (Answer: start())

Creating Threads

4

Two Ways to Create Threads

# ============================================================
# TWO WAYS TO CREATE THREADS
# ============================================================

import threading
import time

# ============================================================
# METHOD 1: FUNCTION TARGET
# ============================================================

def worker(name, delay):
    """Simulate work"""
    print(f"Worker {name} starting...")
    time.sleep(delay)
    print(f"Worker {name} finished!")

# Create threads using function target
thread1 = threading.Thread(target=worker, args=("Thread-1", 2))
thread2 = threading.Thread(target=worker, args=("Thread-2", 3))

thread1.start()
thread2.start()
thread1.join()
thread2.join()

# ============================================================
# METHOD 2: SUBCLASSING THREAD
# ============================================================

class WorkerThread(threading.Thread):
    """Custom thread class"""
    
    def __init__(self, name, delay):
        threading.Thread.__init__(self)
        self.name = name
        self.delay = delay
    
    def run(self):
        """Code to run in the thread"""
        print(f"Thread {self.name} starting...")
        time.sleep(self.delay)
        print(f"Thread {self.name} finished!")

# Create thread objects
thread3 = WorkerThread("Thread-3", 2)
thread4 = WorkerThread("Thread-4", 3)

thread3.start()
thread4.start()
thread3.join()
thread4.join()

print("All threads finished!")

# ============================================================
# WHICH METHOD TO USE?
# ============================================================

print("""
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Method 1: Function Target                                     β”‚
β”‚ βœ… Simpler and more Pythonic                                   β”‚
β”‚ βœ… Good for simple tasks                                      β”‚
β”‚ βœ… Less boilerplate code                                      β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ Method 2: Subclassing Thread                                  β”‚
β”‚ βœ… More object-oriented                                       β”‚
β”‚ βœ… Better for complex threads                                 β”‚
β”‚ βœ… Can have custom attributes and methods                     β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
""")

Creating threads key points:

  • Function target β€” simpler, recommended for most cases
  • Subclassing Thread β€” for complex thread behavior
  • run() method β€” define thread behavior in subclass
  • __init__ β€” pass custom arguments to thread

Quick Check: What method do you override when subclassing Thread? (Answer: run())

Joining Threads

5

Waiting for Threads to Finish

The join() method makes the main program wait for a thread to finish before continuing.

# ============================================================
# JOINING THREADS
# ============================================================

import threading
import time

# ============================================================
# WITHOUT JOIN - Threads run and program may finish early
# ============================================================

def slow_task(name, seconds):
    print(f"Task {name} started")
    time.sleep(seconds)
    print(f"Task {name} finished")

print("1. WITHOUT JOIN:")
t1 = threading.Thread(target=slow_task, args=("A", 2))
t1.start()
# No join - program may finish before thread completes
print("Main program continuing...")
time.sleep(1)
print("Main program finished (maybe before thread)")

print("\n" + "=" * 40)

# ============================================================
# WITH JOIN - Program waits for thread
# ============================================================

print("\n2. WITH JOIN:")
t2 = threading.Thread(target=slow_task, args=("B", 2))
t2.start()
t2.join()  # Wait for thread to finish
print("Main program finished (after thread)")

print("\n" + "=" * 40)

# ============================================================
# JOIN WITH TIMEOUT
# ============================================================

print("\n3. JOIN WITH TIMEOUT:")

def long_task():
    print("Long task started")
    time.sleep(5)
    print("Long task finished")

t3 = threading.Thread(target=long_task)
t3.start()
t3.join(timeout=2)  # Wait at most 2 seconds

if t3.is_alive():
    print("Thread is still running (timeout reached)")
else:
    print("Thread finished within timeout")

# ============================================================
# JOINING MULTIPLE THREADS
# ============================================================

print("\n4. JOINING MULTIPLE THREADS:")

def work(name):
    print(f"{name} working...")
    time.sleep(1)
    print(f"{name} done!")

threads = []
for i in range(3):
    t = threading.Thread(target=work, args=(f"Thread-{i+1}",))
    threads.append(t)
    t.start()

# Join all threads
for t in threads:
    t.join()

print("All threads finished!")

join() key points:

  • join() β€” waits for thread to finish
  • join(timeout) β€” waits for specified seconds
  • is_alive() β€” checks if thread is still running
  • Important β€” always join threads to avoid race conditions

Quick Check: What does join() do? (Answer: It makes the program wait for the thread to finish)

Daemon Threads

6

Background Threads That Don't Block Program Exit

A daemon thread runs in the background and does not prevent the program from exiting. When all non-daemon threads finish, the program exits, and daemon threads are abruptly stopped.

# ============================================================
# DAEMON THREADS
# ============================================================

import threading
import time

# ============================================================
# 1. NON-DAEMON THREAD (Default)
# ============================================================

print("1. NON-DAEMON THREAD:")

def non_daemon_task():
    for i in range(5):
        print(f"Non-daemon: {i}")
        time.sleep(1)

t1 = threading.Thread(target=non_daemon_task)
t1.start()
# Program waits for this thread to finish
print("Main program - waiting for non-daemon thread...")

# ============================================================
# 2. DAEMON THREAD
# ============================================================

print("\n2. DAEMON THREAD:")

def daemon_task():
    for i in range(10):
        print(f"Daemon: {i}")
        time.sleep(0.5)

t2 = threading.Thread(target=daemon_task)
t2.daemon = True  # Set as daemon
t2.start()

# Program will exit immediately without waiting for daemon
print("Main program - not waiting for daemon thread...")
time.sleep(2)
print("Main program exiting (daemon will be terminated)")

# ============================================================
# 3. DAEMON WITH JOIN
# ============================================================

print("\n3. DAEMON WITH JOIN:")

def background_task():
    for i in range(5):
        print(f"Background: {i}")
        time.sleep(1)

t3 = threading.Thread(target=background_task)
t3.daemon = True
t3.start()
# t3.join()  # Uncomment to wait for daemon
print("Main program - with or without join?")

# ============================================================
# WHEN TO USE DAEMON THREADS
# ============================================================

print("""
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ WHEN TO USE DAEMON THREADS                                    β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ βœ… Background monitoring                                      β”‚
β”‚ βœ… Logging threads                                            β”‚
β”‚ βœ… Health checks                                              β”‚
β”‚ βœ… Periodic cleanup tasks                                     β”‚
β”‚ βœ… Cache refreshing                                           β”‚
β”‚                                                                 β”‚
β”‚ ❌ Critical tasks that must complete                           β”‚
β”‚ ❌ Data processing that must finish                           β”‚
β”‚ ❌ Tasks that need to be reliable                              β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
""")

Daemon threads key points:

  • daemon = True β€” makes thread a daemon
  • Exits with program β€” doesn't block program exit
  • Abrupt termination β€” may not complete its work
  • Best for background tasks β€” not critical operations

Quick Check: What is a daemon thread? (Answer: A background thread that doesn't prevent the program from exiting)

Real-World Example: Download Manager

7

Building a Download Manager with Threads

# ============================================================
# DOWNLOAD MANAGER WITH THREADS
# ============================================================

import threading
import time
import random

class DownloadManager:
    """Simulate a download manager using threads"""
    
    def __init__(self):
        self.downloads = []
        self.completed = 0
        self.lock = threading.Lock()  # For thread safety
    
    def download_file(self, file_name, size_mb):
        """Simulate downloading a file"""
        thread_id = threading.current_thread().name
        
        print(f"[{thread_id}] Starting download: {file_name} ({size_mb}MB)")
        self.downloads.append(file_name)
        
        # Simulate download progress
        for progress in range(0, 101, 10):
            time.sleep(random.uniform(0.2, 0.5))
            print(f"[{thread_id}] {file_name}: {progress}% complete")
        
        # Thread-safe counter update
        with self.lock:
            self.completed += 1
        
        print(f"[{thread_id}] Completed: {file_name}")
        return file_name
    
    def start_downloads(self, files):
        """Start multiple downloads in parallel"""
        threads = []
        
        for file_name, size in files:
            thread = threading.Thread(
                target=self.download_file,
                args=(file_name, size),
                name=f"Download-{file_name[:5]}"
            )
            threads.append(thread)
            thread.start()
        
        # Wait for all downloads to complete
        for thread in threads:
            thread.join()
        
        print(f"\nAll downloads completed! Total: {self.completed} files")
        print(f"Files downloaded: {', '.join(self.downloads)}")

# ============================================================
# RUN THE DOWNLOAD MANAGER
# ============================================================

if __name__ == "__main__":
    manager = DownloadManager()
    
    # List of files to download (name, size in MB)
    files_to_download = [
        ("movie.mp4", 150),
        ("document.pdf", 5),
        ("music.mp3", 10),
        ("image.jpg", 3),
        ("game.exe", 500)
    ]
    
    print("=" * 60)
    print("DOWNLOAD MANAGER")
    print("=" * 60)
    print("Starting downloads in parallel...\n")
    
    start_time = time.time()
    manager.start_downloads(files_to_download)
    end_time = time.time()
    
    print(f"\nTotal time: {end_time - start_time:.2f} seconds")
    print("Downloads completed successfully!")

# ============================================================
# WHY THREADS ARE USEFUL HERE
# ============================================================

print("""
Why threads make this better:
1. Each download runs in its own thread
2. Downloads happen simultaneously
3. Total time = time of slowest download (not sum of all)
4. User interface remains responsive
5. Can add progress tracking and cancellation

Without threads: 5 downloads would take 5x longer!
""")

Real-world example key points:

  • Parallel downloads β€” each file downloads in its own thread
  • Thread safety β€” using locks for shared data
  • Progress tracking β€” each thread reports progress
  • Performance β€” total time is reduced significantly

Quick Check: Why are threads useful for a download manager? (Answer: They allow multiple downloads to happen simultaneously)

Best Practices

8

Threading Best Practices

# ============================================================
# THREADING BEST PRACTICES
# ============================================================

print("1. USE THREAD SAFE DATA STRUCTURES")
print("   - Use Queue for thread-safe communication")
print("   - Use Lock for shared data access")
print("   - Example: from queue import Queue")

print("\n2. ALWAYS JOIN THREADS")
print("   - Ensure threads complete before program exits")
print("   - Prevents resource leaks")

print("\n3. AVOID SHARING MODIFIABLE DATA")
print("   - Pass data through queues")
print("   - Use immutability when possible")

print("\n4. USE DAEMON THREADS FOR BACKGROUND TASKS")
print("   - Don't use for critical operations")
print("   - They may not complete")

print("\n5. HANDLE EXCEPTIONS IN THREADS")
print("   - Exceptions in threads don't propagate to main")
print("   - Use try/except inside thread functions")

print("\n6. LIMIT THE NUMBER OF THREADS")
print("   - Too many threads = performance degradation")
print("   - Use thread pools for many tasks")

print("\n7. USE THREAD POOLS FOR MANY TASKS")
print("   - from concurrent.futures import ThreadPoolExecutor")
print("   - Reuses threads for efficiency")

print("\n8. DON'T USE THREADS FOR CPU-BOUND TASKS")
print("   - Use multiprocessing instead")
print("   - Python's GIL limits CPU-bound threading")

Best practices summary:

  • Use thread-safe structures β€” Queue, Lock
  • Always join threads β€” prevent resource leaks
  • Minimize shared data β€” avoid race conditions
  • Handle exceptions β€” inside thread functions
  • Don't over-thread β€” use thread pools

Quick Check: What should you use for thread-safe communication? (Answer: Queue)

Try It Yourself

Experiment with threads in the editor below.

Loading Pyodide... 0%
Python Code Editor
========================================
THREADS - PRACTICE
========================================

1. CREATING AND STARTING THREADS
----------------------------------------
Thread 'Thread-1' started
Task A: Working...
Task A: Done!
Thread 'Thread-2' started
Task B: Working...
Task B: Done!

2. JOINING THREADS
----------------------------------------
Waiting for thread 'Thread-1' to finish...
Thread 'Thread-1' joined
Waiting for thread 'Thread-2' to finish...
Thread 'Thread-2' joined

3. MULTIPLE THREADS EXAMPLE
----------------------------------------
Thread 'Worker-1' started
Worker 1: Starting
Worker 1: Finished
Thread 'Worker-2' started
Worker 2: Starting
Worker 2: Finished
Thread 'Worker-3' started
Worker 3: Starting
Worker 3: Finished
Waiting for thread 'Worker-1' to finish...
Thread 'Worker-1' joined
Waiting for thread 'Worker-2' to finish...
Thread 'Worker-2' joined
Waiting for thread 'Worker-3' to finish...
Thread 'Worker-3' joined

4. THREADING CONCEPTS SUMMARY
----------------------------------------
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Concept β”‚ Description β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ Thread β”‚ Separate flow of execution β”‚
β”‚ start() β”‚ Begins thread execution β”‚
β”‚ join() β”‚ Waits for thread to finish β”‚
β”‚ Daemon Thread β”‚ Background thread, exits with program β”‚
β”‚ Thread Safety β”‚ Managing shared data between threads β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Threads allow multiple tasks to run concurrently!
πŸ†

You've Got It!

You now understand threads in Python. You know what threads are, why they're useful, and how to create and manage them.

Quick Quiz

Test what you've learned:

1. What is a thread?
2. What method starts a thread?
3. What does join() do?
4. What is a daemon thread?
5. Why should you limit the number of threads?

Frequently Asked Questions

What is the difference between a thread and a process? β–Ό

Threads share memory space and are lightweight. Processes have separate memory and are heavier. Threads are good for I/O tasks; processes are better for CPU-bound tasks.

What is the Global Interpreter Lock (GIL) in Python? β–Ό

The GIL is a mutex that prevents multiple threads from executing Python bytecode at the same time. This means CPU-bound threads don't get true parallelism in CPython. However, I/O-bound threads still benefit significantly.

What is a common interview question about threads? β–Ό

Common questions include: "What is the difference between threads and processes?" "What is the GIL?" "How do you create a thread in Python?" and "What is thread synchronization and why is it important?"

When should I use threading vs asyncio? β–Ό

Use threading for I/O-bound tasks with blocking operations. Use asyncio for high-concurrency I/O operations with async/await. Threading is simpler for most cases; asyncio is more scalable for many connections.

What is thread synchronization? β–Ό

Thread synchronization is the process of controlling access to shared resources to prevent race conditions. Python provides Lock, RLock, Semaphore, and Event for synchronization.

Where to Go From Here

Now that you understand threads, check out these related topics:

Process vs Threads

Learn the key differences between processes and threads.

Learn More β†’

Creating Threads

Deep dive into creating and managing threads.

Learn More β†’

Thread Synchronization

Learn how to safely share data between threads.

Learn More β†’
Interview Resources
  • Python Syntax & Variables Interview Questions
  • Top SQL Interview Questions & Answers
  • SQL Joins: Displaying Data from Multiple Tables FAQ
  • Python Lists and Dictionaries Interview Questions
  • Python OOP Interview Questions
  • SQL Set Operators Interview Questions
Previous: Graphics in Python Next: Process vs Threads β†’