#!/usr/bin/env python3

import threading, time
from concurrent.futures import ThreadPoolExecutor

def fetch_data(source_id):
    """e.g., reading from file"""
    print(f"starting  fetch_data({source_id})")
    time.sleep(2)    # simulated working time
    print(f"finishing fetch_data({source_id})\n")
    return "result " + str(source_id)

start_time = time.time()
print("# --- ------------------ ---")
print("# --- sequential reading ---")
print("# --- ------------------ ---")

sources = [1, 2, 3]

# ThreadPoolExecutor handles starting and joining threads automatically
with ThreadPoolExecutor(max_workers=3) as executor:
    results = executor.map(fetch_data, sources)

for result in results:
    print(result)
