Concurrency with thread pools for waiting work
Concurrency means making progress on several tasks during the same period, for example by switching between them while each waits. Parallelism means running tasks at literally the same instant on different processor cores. A program can be concurrent without being parallel. The two are different tools for different problems.
Python
import time
from concurrent.futures import ThreadPoolExecutor
def fetch(n):
time.sleep(0.2)
return n * n
start = time.perf_counter()
sequential = [fetch(n) for n in range(5)]
sequential_time = time.perf_counter() - start
start = time.perf_counter()
with ThreadPoolExecutor(max_workers=5) as pool:
overlapped = list(pool.map(fetch, range(5)))
overlapped_time = time.perf_counter() - start
print(sequential == overlapped, overlapped)
print(overlapped_time < sequential_time / 2)