📘 Premium Read: Access my best content on Medium member-only articles — deep dives into Java, Spring Boot, Microservices, backend architecture, interview preparation, career advice, and industry-standard best practices.
🎓 Top 15 Udemy Courses (80-90% Discount): My Udemy Courses - Ramesh Fadatare — All my Udemy courses are real-time and project oriented courses.
▶️ Subscribe to My YouTube Channel (176K+ subscribers): Java Guides on YouTube
▶️ For AI, ChatGPT, Web, Tech, and Generative AI, subscribe to another channel: Ramesh Fadatare on YouTube
Introduction
Multithreading is a technique that allows multiple threads to run concurrently, sharing the same resources. In Python, multithreading is commonly used to perform multiple tasks simultaneously to improve the efficiency and performance of applications. This tutorial covers everything you need to know about multithreading in Python, including creating, starting, and managing threads, thread synchronization, and practical examples.
Table of Contents
- What is Multithreading?
- Python Threading Module
- Creating and Starting Threads
- Joining Threads
- Thread Synchronization
- Thread Communication
- Daemon Threads
- Thread Pools
- Practical Examples
- Conclusion
1. What is Multithreading?
Multithreading is a programming technique where multiple threads run concurrently, allowing for parallel execution of tasks. Each thread runs independently and can be used to perform a specific task within a larger program.
2. Python Threading Module
Python's threading
module provides a way to create and manage threads. This module offers a higher-level interface for threading compared to the lower-level _thread
module.
3. Creating and Starting Threads
You can create a thread by instantiating the Thread
class from the threading
module. The target function and its arguments are passed to the Thread
constructor.
Example
import threading def print_numbers(): for i in range(5): print(i) # Creating a thread thread = threading.Thread(target=print_numbers) # Starting the thread thread.start() # Main thread continues to run print("Main thread continues to run")
Output
Main thread continues to run 0 1 2 3 4
4. Joining Threads
The join()
method is used to wait for a thread to complete its execution before proceeding with the rest of the program.
Example
import threading def print_numbers(): for i in range(5): print(i) # Creating a thread thread = threading.Thread(target=print_numbers) # Starting the thread thread.start() # Waiting for the thread to complete thread.join() print("Thread has finished execution")
Output
0 1 2 3 4 Thread has finished execution
5. Thread Synchronization
Thread synchronization is crucial when multiple threads access shared resources. Python provides several synchronization primitives such as Lock
, RLock
, Semaphore
, Event
, and Condition
.
Example: Using Lock
import threading lock = threading.Lock() counter = 0 def increment_counter(): global counter for _ in range(100000): lock.acquire() counter += 1 lock.release() threads = [] for _ in range(5): thread = threading.Thread(target=increment_counter) threads.append(thread) thread.start() for thread in threads: thread.join() print("Counter value:", counter)
Output
Counter value: 500000
6. Thread Communication
Threads can communicate with each other using thread-safe queues. Python's queue
module provides Queue
, which is a thread-safe FIFO implementation.
Example: Using Queue
import threading import queue import time def producer(q): for i in range(5): time.sleep(1) item = f"item-{i}" q.put(item) print(f"Produced {item}") def consumer(q): while True: item = q.get() if item is None: break print(f"Consumed {item}") q.task_done() q = queue.Queue() producer_thread = threading.Thread(target=producer, args=(q,)) consumer_thread = threading.Thread(target=consumer, args=(q,)) producer_thread.start() consumer_thread.start() producer_thread.join() q.put(None) # Signal the consumer to exit consumer_thread.join()
Output
Produced item-0 Consumed item-0 Produced item-1 Consumed item-1 Produced item-2 Consumed item-2 Produced item-3 Consumed item-3 Produced item-4 Consumed item-4
7. Daemon Threads
Daemon threads run in the background and do not block the program from exiting. They are terminated when the main thread exits.
Example
import threading import time def background_task(): while True: print("Background task is running") time.sleep(1) daemon_thread = threading.Thread(target=background_task) daemon_thread.setDaemon(True) # Set the thread as a daemon thread daemon_thread.start() time.sleep(3) print("Main thread is exiting")
Output
Background task is running Background task is running Background task is running Main thread is exiting
8. Thread Pools
Thread pools manage a pool of worker threads to execute tasks. The concurrent.futures
module provides ThreadPoolExecutor
for this purpose.
Example
from concurrent.futures import ThreadPoolExecutor def square_number(number): return number * number numbers = [1, 2, 3, 4, 5] with ThreadPoolExecutor(max_workers=3) as executor: results = executor.map(square_number, numbers) for result in results: print(result)
Output
1 4 9 16 25
9. Practical Examples
Example 1: Downloading Files Concurrently
import threading import requests def download_file(url): response = requests.get(url) file_name = url.split("/")[-1] with open(file_name, "wb") as file: file.write(response.content) print(f"Downloaded {file_name}") urls = [ "https://example.com/file1.txt", "https://example.com/file2.txt", "https://example.com/file3.txt" ] threads = [] for url in urls: thread = threading.Thread(target=download_file, args=(url,)) threads.append(thread) thread.start() for thread in threads: thread.join() print("All files downloaded")
Example 2: Processing Data Concurrently
import threading data = [1, 2, 3, 4, 5] processed_data = [] def process_item(item): result = item * 2 processed_data.append(result) threads = [] for item in data: thread = threading.Thread(target=process_item, args=(item,)) threads.append(thread) thread.start() for thread in threads: thread.join() print("Processed Data:", processed_data)
10. Conclusion
Multithreading in Python allows you to perform multiple tasks concurrently, improving the efficiency and performance of your programs. By understanding how to create, start, join, and synchronize threads, you can leverage the power of multithreading in your applications. This tutorial covered the basics of multithreading, including creating threads, synchronization, communication, daemon threads, and thread pools, along with practical examples to help you get started.
Comments
Post a Comment
Leave Comment