스레드 풀(Thread Pool)은 미리 생성된 스레드 집합을 재사용해 작업을 처리하는 패턴이다. 작업마다 새 스레드를 생성/소멸하는 오버헤드를 없애고, 동시 스레드 수를 제한해 시스템 자원을 보호한다.
기본 구조
작업 큐
┌─────────────────┐
│ Task1 Task2 ... │
└────────┬────────┘
│ 작업 분배
┌────────▼────────────────────┐
│ 스레드 풀 │
│ Thread-1 Thread-2 Thread-3 │ ← 미리 생성된 N개 스레드
└─────────────────────────────┘
python
from concurrent.futures import ThreadPoolExecutor, ProcessPoolExecutor
import time
def fetch_data(url):
time.sleep(0.1) # I/O 시뮬레이션
return f"data from {url}"
urls = [f"https://api.example.com/{i}" for i in range(20)]
# ThreadPoolExecutor: I/O 바운드 작업
with ThreadPoolExecutor(max_workers=5) as executor:
results = list(executor.map(fetch_data, urls))
# 5개 스레드로 20개 작업 처리 → ~0.4초 (순차: 2초)
# ProcessPoolExecutor: CPU 바운드 작업 (GIL 우회)
with ProcessPoolExecutor(max_workers=4) as executor:
futures = [executor.submit(cpu_heavy_task, x) for x in data]
results = [f.result() for f in futures]
Java ExecutorService
java
ExecutorService pool = Executors.newFixedThreadPool(10);
for (int i = 0; i < 100; i++) {
pool.submit(() -> {
// 작업 수행
processRequest();
});
}
pool.shutdown(); // 현재 작업 완료 후 종료
스레드 풀 크기 결정
I/O 바운드: N = 코어 수 × (1 + 대기 시간/처리 시간)
CPU 바운드: N = 코어 수 (보통 코어수 + 1)
예: 8코어, I/O 대기 90% → N = 8 × 10 = 80
관련 개념
- •프로세스와 스레드 — 스레드 풀의 기반 단위
- •동시성 — 스레드 풀이 구현하는 목표
- •메시지 큐 — 작업 큐와 스레드 풀의 조합
- •비동기 I/O — 스레드 풀의 대안