threading과 multiprocessing은 인터페이스가 다르고 약간 번거롭습니다.
concurrent.futures가 「ThreadPoolExecutor·ProcessPoolExecutor」로 둘을 통일된 API로 제공해 훨씬 쓰기 편합니다.
ThreadPoolExecutor.
from concurrent.futures import ThreadPoolExecutor.
with ThreadPoolExecutor(max_workers=10) as ex: results = list(ex.map(fetch, urls)).
10개 스레드가 100개 URL 분담 — IO 바운드에 적합.
ProcessPoolExecutor.
with ProcessPoolExecutor(max_workers=4) as ex: results = list(ex.map(heavy_compute, data)).
4개 프로세스로 CPU 바운드 작업 병렬.
인터페이스가 같아서 Thread → Process 교체가 한 줄.
submit과 Future.
future = ex.submit(func, arg).
즉시 시작 + Future 객체 반환.
나중에 future.result()로 결과 수령.
as_completed(futures)로 「끝난 순서대로」 처리도 가능.
선택.
IO 바운드 → ThreadPoolExecutor(또는 더 모던하게 asyncio).
CPU 바운드 → ProcessPoolExecutor.
학습 비용 낮고 효과 크니 「병렬」이 떠오르면 일단 concurrent.futures를 첫 후보로.
한 줄 요약
concurrent.futures는 Thread·Process Pool을 통일된 API로 제공.
ex.map이 표준, submit·as_completed로 더 세밀한 제어.
학습 쉽고 효과 큰 첫 선택지.
더 알아볼 것
- map vs submit 차이
- ThreadPool vs asyncio 선택
- Pool 크기 결정 — IO는 크게, CPU는 코어 수