Multithreaded computation executes work across multiple threads within one program. It enables parallelism, unlike concurrency that mainly coordinates tasks while they wait, and is useful for CPU-heavy calculations or resource-bound libraries. section 8.4
A practical threading model involves:
- Creating operating-system threads for individual calculations rather than relying only on asynchronous scheduling. section 8.4
- Using several workers to increase throughput, while accepting that completion order is not guaranteed. section 8.4
- Checking the machine and runtime: four workers cannot provide the expected speedup without enough cores, and Python’s single-process design limits improvement. section 8.4
Rendering Mandelbrot images
A Python program renders eight Mandelbrot images. Replacing sleep-based asyncio scheduling with ThreadPoolExecutor(max_workers=4) submits each calculation to a worker thread while asyncio.gather coordinates the requests. section 8.3 section 8.4
Listing 8.7 main.py: Adding execution threads
from concurrent.futures import ThreadPoolExecutor
import asyncio
def mandelbrot_func:
...
executor = ThreadPoolExecutor(max_workers=4)
async def mandelbrot(size: int, path: str, range_x0: float, range_y0: float,
range_x1: float, range_y1: float):
return executor.submit(mandelbrot_func, size, path, range_x0, range_y0,
range_x1, range_y1)
async def main():
await asyncio.gather(*[
mandelbrot(1000, f"purp{i}.png", -5.0, -2.12, -2.5, 1.12)
for i in range(0,8)
])
Inspect the complete ThreadPoolExecutor example, including worker creation, task submission, and asynchronous coordination. section 8.4










