89 lines
9.2 KiB
Markdown
89 lines
9.2 KiB
Markdown
---
|
|
title: "JDK 21 ThreadPoolExecutor Javadoc — Pool Sizing, Queue Policy, Rejection Handlers"
|
|
source_type: official-doc
|
|
url: https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/util/concurrent/ThreadPoolExecutor.html
|
|
archive_url:
|
|
related_branches: [feature-background-job-async-contract]
|
|
related_projects: [ca-skeleton]
|
|
tags: [official-doc, ca-skeleton, runtime, java-21, pool-sizing]
|
|
created: 2026-06-11
|
|
---
|
|
|
|
# JDK 21 ThreadPoolExecutor Javadoc — Pool Sizing, Queue Policy, Rejection Handlers
|
|
|
|
> Layer: `raw/` — Oracle Java SE 21 공식 API Javadoc 원문 발췌·출처 기록.
|
|
> 검증된 요약은 `/ingest` 후 `wiki/concepts/` 에 별도 작성. 원본은 raw 에 영구 보관.
|
|
|
|
## Parent / 활용 branch (필수)
|
|
|
|
| Branch | 이 자료가 정당화하는 결정 |
|
|
|---|---|
|
|
| [[raw/branch-notes/feature-background-job-async-contract]] | D7 — pool growth 3단계(core→queue→max), bounded queue 의 resource-exhaustion 방지, AbortPolicy/CallerRunsPolicy 시맨틱, unbounded queue 에서 maximumPoolSize 무효 — executor sizing/saturation 구조 근거. |
|
|
|
|
## 출처 / Source
|
|
|
|
- 원본 URL: https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/util/concurrent/ThreadPoolExecutor.html
|
|
- 아카이브 URL: (미등록)
|
|
- 저자 / 조직: Oracle Corporation
|
|
- 발행일: Java SE 21 (2023-09-19 GA)
|
|
- 마지막 확인일: 2026-06-11
|
|
|
|
## 왜 저장했는지 / Why archived
|
|
|
|
`feature-background-job-async-contract` 의 D7 결정 — executor saturation 시 AbortPolicy 기본값 채택, CallerRunsPolicy 제한적 허용, bounded queue 채택, unbounded queue 금지 — 은 JDK 공식 Javadoc 이 명시하는 pool growth 3단계 시맨틱과 bounded/unbounded queue 트레이드오프에 직접 근거를 둔다. UNSUPPORTED_DECISION 에서 공식 근거로 승격하기 위해 보관.
|
|
|
|
## 핵심 인용 / Key quotes (verbatim, 3~5문장)
|
|
|
|
> [§Core and maximum pool sizes] "If fewer than corePoolSize threads are running, the Executor always prefers adding a new thread rather than queuing. If corePoolSize or more threads are running, the Executor always prefers queuing a request rather than adding a new thread. If a request cannot be queued, a new thread is created unless this would exceed maximumPoolSize, in which case, the task will be rejected."
|
|
|
|
> [§Queuing — Unbounded queues] "Using an unbounded queue (for example a LinkedBlockingQueue without a predefined capacity) will cause new tasks to wait in the queue when all corePoolSize threads are busy. Thus, no more than corePoolSize threads will ever be created. (And the value of the maximumPoolSize therefore doesn't have any effect.)"
|
|
|
|
> [§Queuing — Bounded queues] "A bounded queue (for example, an ArrayBlockingQueue) helps prevent resource exhaustion when used with finite maximumPoolSizes, but can be more difficult to tune and control."
|
|
|
|
> [§Rejected tasks — AbortPolicy] "In the default ThreadPoolExecutor.AbortPolicy, the handler throws a runtime RejectedExecutionException upon rejection."
|
|
|
|
> [§Rejected tasks — CallerRunsPolicy] "In ThreadPoolExecutor.CallerRunsPolicy, the thread that invokes execute itself runs the task. This provides a simple feedback control mechanism that will slow down the rate that new tasks are submitted."
|
|
|
|
## Claims Extracted / 추출된 주장
|
|
|
|
> 이 자료가 **직접 말하는 것만** claim 으로 분리한다. 내 프로젝트에 적용한 결론은 여기 쓰지 않는다.
|
|
|
|
| Claim ID | Claim (이 자료가 직접 말하는 것) | Evidence quote | Strength | Applies to | Does not prove |
|
|
|---|---|---|---|---|---|
|
|
| TPE-JDK21-C1 | pool growth 는 core → queue → max 의 3단계 순서로 진행된다. corePoolSize 미만이면 항상 새 스레드를 추가한다. | [§Core and maximum pool sizes] "If fewer than corePoolSize threads are running, the Executor always prefers adding a new thread rather than queuing." | `official-reference` | JDK 21 `ThreadPoolExecutor` (및 하위 버전 동일 시맨틱) | Spring `ThreadPoolTaskExecutor` 가 동일 규칙을 따른다는 것을 직접 증명하지는 않는다 (별도 위임 구조 확인 필요). 특정 corePoolSize 수치의 적합성. |
|
|
| TPE-JDK21-C2 | queue 용량 초과 시에만 max 까지 스레드를 늘리며, max 도달 후 거부된다. | [§Core and maximum pool sizes] "If a request cannot be queued, a new thread is created unless this would exceed maximumPoolSize, in which case, the task will be rejected." | `official-reference` | JDK 21 `ThreadPoolExecutor` | max 도달 시 어떤 RejectedExecutionHandler 가 적용되는지는 별도 정책 설정에 따른다 (기본값은 AbortPolicy). |
|
|
| TPE-JDK21-C3 | unbounded queue 사용 시 maximumPoolSize 는 사실상 무효화된다 — corePoolSize 이상의 스레드가 절대 생성되지 않는다. | [§Queuing — Unbounded queues] "no more than corePoolSize threads will ever be created. (And the value of the maximumPoolSize therefore doesn't have any effect.)" | `official-reference` | `LinkedBlockingQueue` 등 capacity 지정 없는 unbounded queue 사용 시 | bounded queue 가 더 낫다는 것을 직접 권고하지 않는다. resource exhaustion 의 구체적 임계값 또는 메모리 상한도 명시하지 않는다. |
|
|
| TPE-JDK21-C4 | bounded queue 는 resource exhaustion 방지에 유효하지만 튜닝이 더 어렵다. | [§Queuing — Bounded queues] "A bounded queue (for example, an ArrayBlockingQueue) helps prevent resource exhaustion when used with finite maximumPoolSizes, but can be more difficult to tune and control." | `official-reference` | finite maximumPoolSize 와 함께 사용되는 bounded queue | 적절한 queue capacity 수치(예: 200)의 정당성. 특정 부하 프로파일에서의 성능 특성. |
|
|
| TPE-JDK21-C5 | AbortPolicy(기본값)는 거부 시 `RejectedExecutionException` 을 throw 한다. | [§Rejected tasks — AbortPolicy] "the handler throws a runtime RejectedExecutionException upon rejection." | `official-reference` | JDK 21 `ThreadPoolExecutor.AbortPolicy` | 어떤 예외 핸들링 전략이 특정 애플리케이션에 적합한지. 예외 발생이 caller 에게 어디까지 전파되는지(async context 에서 동작 방식 별도 확인 필요). |
|
|
| TPE-JDK21-C6 | CallerRunsPolicy 는 호출 스레드가 직접 task 를 실행해 제출 속도를 자동 감소시키는 피드백 제어 메커니즘을 제공한다. | [§Rejected tasks — CallerRunsPolicy] "This provides a simple feedback control mechanism that will slow down the rate that new tasks are submitted." | `official-reference` | `ThreadPoolExecutor.CallerRunsPolicy` | 피드백 감속이 특정 부하 패턴에서 안전한지. `@Async` 메서드에서 CallerRunsPolicy 사용 시 요청 스레드(HTTP 서블릿 스레드 등)를 block 하는 부작용이 없다는 것을 증명하지 않는다. |
|
|
|
|
## Usage Boundaries / 적용 경계
|
|
|
|
- 이 자료가 직접 증명하는 것:
|
|
- `TPE-JDK21-C1`, `TPE-JDK21-C2`: JDK `ThreadPoolExecutor` 의 pool growth 시맨틱(core→queue→max 3단계, 거부 트리거 조건)
|
|
- `TPE-JDK21-C3`: unbounded queue 사용 시 maximumPoolSize 가 무의미해지는 시맨틱
|
|
- `TPE-JDK21-C4`: bounded queue 가 resource exhaustion 을 방지하는 수단임
|
|
- `TPE-JDK21-C5`: AbortPolicy 가 기본값이며 `RejectedExecutionException` 을 throw 한다는 시맨틱
|
|
- `TPE-JDK21-C6`: CallerRunsPolicy 가 피드백 감속 메커니즘을 제공한다는 시맨틱
|
|
- 이 자료가 증명하지 않는 것:
|
|
- ca-tmpl 에 적합한 구체적인 core/max/queue 수치(예: 10/50/200)의 정당성
|
|
- Spring `ThreadPoolTaskExecutor` 가 `ThreadPoolExecutor` 에 위임해 동일 growth 규칙을 따른다는 것 (Spring 공식 doc 별도 확인 필요)
|
|
- `@Async` + CallerRunsPolicy 조합이 HTTP 서블릿 스레드를 block 하지 않는다는 것
|
|
- unbounded queue 가 특정 환경에서 OOM 을 유발하는 임계 수치
|
|
- 내 프로젝트에 적용하려면 추가 확인이 필요한 것:
|
|
- Spring `ThreadPoolTaskExecutor` Javadoc 에서 `ThreadPoolExecutor` 위임 구조 확인 (D7 의 Spring-layer 적용)
|
|
- ca-tmpl 부하 프로파일 기반 core=10/max=50/queue=200 수치 검증 (부하 테스트 또는 Spring Boot 기본값 doc 확인)
|
|
- `@Async` context 에서 AbortPolicy 예외가 `AsyncUncaughtExceptionHandler` 로 라우팅되는지 여부
|
|
|
|
## 메모 / Notes
|
|
|
|
- `ThreadPoolExecutor` 와 Spring `ThreadPoolTaskExecutor` 의 관계: `ThreadPoolTaskExecutor` 는 내부적으로 `ThreadPoolExecutor` 에 위임하므로 본 Javadoc 의 시맨틱이 동일하게 적용될 가능성이 높으나, Spring 공식 doc 에서 별도 확인 권고.
|
|
- D7 의 `queue=200` 수치: 본 Javadoc 은 bounded queue 사용을 권장하나 구체적 수치 권고는 없음 — 이 수치는 `UNSUPPORTED_IMPL_DECISION` 으로 유지, 부하 테스트로 검증 필요.
|
|
- CallerRunsPolicy 제한적 허용 결정(D7): 본 Javadoc 은 CallerRunsPolicy 의 피드백 감속 효과를 기술하지만 HTTP 요청 스레드 block 위험은 별도 판단 영역.
|
|
|
|
## Related / 관련
|
|
|
|
- Spring `ThreadPoolTaskExecutor` 공식 doc (Spring Framework Javadoc) — D7 의 Spring-layer 검증에 필요
|
|
- Spring Boot `@EnableAsync` / `AsyncConfigurer` 공식 doc — executor bean 등록 방식 근거
|
|
- [[raw/branch-notes/feature-background-job-async-contract]] — 본 자료를 인용하는 branch note
|