Python Thread Pool: Efficient Multithreading with ThreadPoolExecutor
Learn how to efficiently manage multiple tasks using a thread pool in Python. The ThreadPoolExecutor class from the concurrent.futures module helps control thread creation and asynchronous task execution, making it ideal for handling multithreading in Python.
What is a Thread Pool?
A thread pool automatically manages a pool of worker threads. Each thread in the pool is called a worker thread and can be reused once its task is completed. A thread pool controls thread creation and task execution, making it efficient for managing multiple tasks.
In Python, the ThreadPoolExecutor class in the concurrent.futures module allows asynchronous execution of functions by multiple threads.
Key Classes in concurrent.futures Module:
- Future Class
- ThreadPoolExecutor Class
- ProcessPoolExecutor Class
The Future Class
The concurrent.futures.Future class handles asynchronous execution of any callable, such as a function. To get a Future object, call the submit() method on an Executor object.
Important Methods in Future Class:
result(timeout=None): Returns the value from the callable, or raises aTimeoutErrorif not completed in the specified time.cancel(): Attempts to cancel the callable. ReturnsTrueif successful,Falseotherwise.cancelled(): ReturnsTrueif the callable was successfully cancelled.running(): ReturnsTrueif the callable is currently running and cannot be cancelled.done(): ReturnsTrueif the callable was successfully cancelled or finished running.
The ThreadPoolExecutor Class
The ThreadPoolExecutor class represents a pool of worker threads for executing calls asynchronously.
Syntax:
Syntax
concurrent.futures.ThreadPoolExecutor(max_threads)
Example:
Below is an example of using the ThreadPoolExecutor class:
Example
from concurrent.futures import ThreadPoolExecutor
from time import sleep
def square(numbers):
for val in numbers:
ret = val * val
sleep(1)
print("Number:{} Square:{}".format(val, ret))
def cube(numbers):
for val in numbers:
ret = val * val * val
sleep(1)
print("Number:{} Cube:{}".format(val, ret))
if __name__ == '__main__':
numbers = [1, 2, 3, 4, 5]
executor = ThreadPoolExecutor(4)
thread1 = executor.submit(square, (numbers))
thread2 = executor.submit(cube, (numbers))
print("Thread 1 executed ? :", thread1.done())
print("Thread 2 executed ? :", thread2.done())
sleep(2)
print("Thread 1 executed ? :", thread1.done())
print("Thread 2 executed ? :", thread2.done())
Output
Thread 1 executed ? : False
Thread 2 executed ? : False
Number:1 Square:1
Number:1 Cube:1
Number:2 Square:4
Number:2 Cube:8
Thread 1 executed ? : False
Thread 2 executed ? : False
Number:3 Square:9
Number:3 Cube:27
Number:4 Square:16
Number:4 Cube:64
Number:5 Square:25
Number:5 Cube:125
Thread 1 executed ? : True
Thread 2 executed ? : True