Java / JVMadvanced검토 2026.08

Executor와 Thread Pool

작업 제출과 실행 자원을 분리해 동시 실행량과 대기열을 통제한다.

#ExecutorService#ThreadPoolExecutor

Overview

Worker를 재사용하고 Queue로 유입 속도와 처리 속도의 차이를 흡수한다.

핵심 원리

무제한 Queue는 거절 대신 메모리와 지연을 누적하고 Worker 증가는 하위 자원 고갈을 부를 수 있다.

flowchart LR; R[요청] --> Q[Work Queue]; Q --> W1[Worker 1]; Q --> W2[Worker N]; Q -.포화.-> X[Reject]
Executor와 Thread Pool 동작 흐름

실무에서 발생하는 문제

무제한 Queue는 Memory와 대기 시간을 키우고, 작은 Pool에서 Blocking I/O가 길어지면 모든 작업이 정체된다. Task 예외가 관측되지 않거나 종료 시 남은 작업이 유실되는 문제도 있다.

Trade-off

큰 Pool은 동시성을 늘리지만 Context Switching과 하위 시스템 부하를 키운다. 작은 Pool과 유한 Queue는 보호 효과가 있지만 빠른 거절과 재시도 정책이 필요하다.

흔한 오해

Thread 수를 늘리면 처리량이 계속 증가하지 않는다. DB Connection, CPU, 외부 API Rate Limit 중 가장 좁은 자원이 전체 한계를 정한다.

Interview Questions

  • 이 기술이 해결하는 핵심 문제는 무엇인가?
  • 내부에서는 어떤 순서로 동작하는가?
  • 운영 환경에서 어떤 지표와 실패 모드를 확인해야 하는가?

왜 필요한가

Thread 생성 비용을 반복하지 않고 동시 실행 수와 Queue를 제한한다. 요청 폭증을 무한한 Thread가 아니라 명시적인 대기·거절 정책으로 흡수한다.

내부 동작

ThreadPoolExecutor는 Core Thread, 최대 Thread, Work Queue, Keep-alive, Rejection Handler로 동작한다. Queue 종류에 따라 최대 Thread까지 늘어나는 시점이 달라진다. 작업 완료·실패와 Executor 종료도 별도로 관리한다.

Example

CPU 작업은 Core 수 중심으로, Blocking I/O는 대기 비율을 고려하되 하위 Connection Pool보다 과도하게 잡지 않는다. 유한 Queue가 찼을 때 CallerRunsPolicy는 호출 측을 늦춰 자연스러운 Backpressure를 줄 수 있지만 요청 Thread 특성을 확인한다.

Production Considerations

Active Thread, Pool Size, Queue Depth, Task 대기/실행 시간, Rejection, 예외를 측정한다. Shutdown에서 신규 작업 수락을 중단하고 제한 시간 동안 기존 작업을 마친 뒤 강제 종료하는 순서를 시험한다.

Connection Pool, Producer–Consumer, Virtual Thread와 용량 경계를 비교한다.

SOURCE REFERENCES

이 문서의 근거

본문은 Dev Atlas 안에서 완결되며, 검증이 필요할 때만 원문을 확인할 수 있습니다.

원문 출처 보기 2