48: Multithreading in Python: Boosting Performance with Threads

Multithreading in Python: Boosting Performance with Threads

Multithreading can seem like an abstract concept, but it’s a powerful tool for enhancing the performance of your Python programs. By using threads, you can run multiple operations in parallel, reducing the overall time your program spends waiting on tasks like fetching data from a server or performing long computations. In this blog post, we’ll dive into the basics of multithreading with a practical example.

Why Use Multithreading?

  • Improved Performance: Run tasks concurrently, reducing wait times.
  • Efficient Resource Use: Make better use of system resources by allowing other tasks to run while waiting for I/O operations.
  • Responsiveness: Enhance the responsiveness of applications by handling multiple tasks at once.

Example Code: Multithreading in Python

Let’s walk through an example where we calculate the squares of several numbers using multithreading.

Step 1: Import Required Modules

First, we need to import the threading and time modules.

				
					import threading
import time

				
			

Step 2: Define a Long-Running Function

We’ll create a function longSquare that simulates a time-consuming task by sleeping for a second before returning the square of a number.

				
					def longSquare(n, results):
    time.sleep(1)
    results[n] = n * n

				
			

Step 3: Create and Start Threads

We’ll create two threads to run the longSquare function concurrently.

				
					results = {}

# Create threads
t1 = threading.Thread(target=longSquare, args=(2, results))
t2 = threading.Thread(target=longSquare, args=(3, results))

# Start threads
t1.start()
t2.start()

# Wait for threads to complete
t1.join()
t2.join()

print("Results:", results)

				
			

In this example, the results are stored in a shared dictionary results. Threads can modify the same object, demonstrating the shared memory feature of threads.

Step 4: Scaling Up with Multiple Threads

To handle a larger number of tasks, we can create a list of threads.

				
					results = {}
threads = []

# Create and start multiple threads
for n in range(10):
    thread = threading.Thread(target=longSquare, args=(n, results))
    threads.append(thread)
    thread.start()

# Wait for all threads to complete
for thread in threads:
    thread.join()

print("Results:", results)

				
			

This code snippet creates and starts 10 threads, each calculating the square of a number from 0 to 9. Using a loop to start and join threads simplifies the process, especially when dealing with many threads.

Running with 100 Threads

For fun, let’s scale up to 100 threads and observe the performance improvement.

				
					results = {}
threads = []

# Create and start 100 threads
for n in range(100):
    thread = threading.Thread(target=longSquare, args=(n, results))
    threads.append(thread)
    thread.start()

# Wait for all threads to complete
for thread in threads:
    thread.join()

print("Results:", results)

				
			

You will notice that the task completes much faster compared to running the calculations sequentially.

Conclusion

Multithreading is a powerful tool for improving the performance and responsiveness of your Python programs. By running tasks concurrently, you can make better use of system resources and reduce wait times. In this example, we demonstrated how to use the threading module to perform long-running computations in parallel. Experiment with multithreading in your projects to see the benefits firsthand.