Are your Python programs too slow? Threads, Multiprocessing and Asyncio can be used.
Maybe they are stuck waiting on a file to load, a website to respond, or a CPU-heavy task to finish? Well, my friend, welcome to the world of concurrency!
- Threads – multiple tasks at once.
- Multiprocessing – Splitting the work across multiple CPUs.
- Asyncio – Multitasking while waiting.
Here are some examples:
THREADS
Threads are processes that occur when your program is waiting on some other function (like downloads, database queries, or API requests).
- Example: Running multiple tasks at the same time
import threading import time def print_numbers(): for i in range(5): time.sleep(1) #delay print(f"Number: {i}") # Creating two threads doing the same thing thread1 = threading.Thread(target=print_numbers) thread2 = threading.Thread(target=print_numbers) thread1.start() thread2.start() thread1.join() thread2.join() print("Done!")
Instead of waiting for one function to finish before running the next, Python starts both threads together, so they run at the same time.
- Best for: Tasks that spend time waiting (file input output, API calls)
- Not good for: CPU-heavy work (parallel execution)
MULTIPROCESSING
Multiprocessing is used when your program is doing heavy calculations (like image processing, number crunching).
- Example: Using multiple processors to calculate squares
import multiprocessing def square(num): return num * num if __name__ == "__main__": with multiprocessing.Pool() as pool: results = pool.map(square, range(1, 6)) print(results) # [1, 4, 9, 16, 25]
Each number is sent to a separate processor to be squared at the same time. This makes it much faster.
- Best for: Complex math, image processing, simulations
- Not good for: Simple input output tasks (overhead is high)
ASYNCIO
Asyncio is used when handling thousands of tasks at once, like chat apps or web scraping.
Example: Fetching multiple URLs at the same time
import asyncio async def greet(name): await asyncio.sleep(1) #delay print(f"Hello, {name}!") async def main(): tasks = [greet("Alice"), greet("Bob"), greet("Charlie")] await asyncio.gather(*tasks) # Runs them all at once asyncio.run(main())
Instead of waiting for one greeting to finish before starting the next, all are started together and switches whenever one is waiting.
Tasks run on a single thread but uses an event loop to switch between them whenever one encounters an await
statement.
- Best for: Handling thousands of requests, chat apps, real-time dashboards
- Not good for: CPU-heavy tasks (single thread)
Threads vs. Multiprocessing vs. Asyncio

So next time your program feels slow, choose the right tool for concurrency!