F-LAB JAVA · 4주차 · Phase 7 · Executor 프레임워크
★ 마스터 Unit — 면접 핵심 (★★★) + 4주차 2차 정점의 정점
이 Unit을 끝내면 다음을 답할 수 있어야 한다.
ThreadPoolExecutor 는 corePoolSize, maximumPoolSize, keepAliveTime, workQueue, threadFactory, rejectedExecutionHandler 로 구성되며, 작업 추가 시 "코어 스레드 → 작업 큐 → 최대 스레드 → 거부" 순서로 처리한다.
corePoolSize는 평상시 유지하는 스레드 수,maximumPoolSize는 최대 스레드 수,keepAliveTime은 코어를 초과한 유휴 스레드가 정리되기까지의 시간이다.
작업 추가 흐름의 정확한 순서는 (1) 코어 스레드 수보다 적으면 새 코어 스레드 생성, (2) 코어가 다 차면 작업 큐에 적재, (3) 큐도 가득 차면 max 까지 새 스레드 생성, (4) max 도 다 차고 큐도 가득 차면 거부 다.
가장 헷갈리는 포인트는 큐가 max 보다 먼저 채워진다 는 점이다 — 코어가 차면 바로 max 로 늘리는 게 아니라 큐에 먼저 쌓고, 큐가 가득 차야 max 까지 확장한다.
큐가 가득 차고 max 스레드도 모두 사용 중일 때rejectedExecutionHandler(거부 정책) 가 동작한다.
ThreadPoolExecutor = 식당 운영:
corePoolSize = 기본 직원 (예: 4명):
- 평상시 유지
- 항상 대기
maximumPoolSize = 최대 직원 (예: 10명):
- 바쁠 때 임시 직원 추가
workQueue = 대기 의자 (예: 20석):
- 손님 대기 공간
keepAliveTime = 임시 직원 해고 시간:
- 한가하면 임시 직원 (core 초과) 정리
손님(작업) 처리 순서:
1. 기본 직원 4명 미만이면 → 새 기본 직원 (core)
2. 기본 직원 다 바쁘면 → 대기 의자 (큐)
3. 대기 의자도 다 차면 → 임시 직원 추가 (max)
4. 임시 직원도 다 바쁘고 의자도 가득 → 손님 거부
핵심 (헷갈림):
- "기본 직원 차면 바로 임시 직원" 아님!
- 기본 직원 차면 → 의자 먼저
- 의자 가득 → 그제서야 임시 직원
→ 흐름: core → 큐 → max → 거부 (큐가 max 보다 먼저!).
1. ThreadPoolExecutor 파라미터
2. corePoolSize vs maximumPoolSize
3. keepAliveTime
4. workQueue
5. 작업 추가 흐름 (핵심)
6. 큐가 max보다 먼저 (헷갈림)
7. 거부 정책
8. 코어 스레드 제어
9. 면접 + 자기 점검 + 마스터 50문항
public ThreadPoolExecutor(
int corePoolSize, // 1. 코어 스레드 수
int maximumPoolSize, // 2. 최대 스레드 수
long keepAliveTime, // 3. 유휴 스레드 생존 시간
TimeUnit unit, // 4. 시간 단위
BlockingQueue<Runnable> workQueue, // 5. 작업 큐
ThreadFactory threadFactory, // 6. 스레드 팩토리
RejectedExecutionHandler handler // 7. 거부 정책
)
핵심 파라미터:
1. corePoolSize
- 기본 유지 스레드
2. maximumPoolSize
- 최대 스레드
3. keepAliveTime
- 유휴 스레드 정리 시간
4. workQueue
- 작업 큐
5. rejectedExecutionHandler
- 거부 정책
(+threadFactory, unit)
ThreadPoolExecutor executor = new ThreadPoolExecutor(
4, // core
10, // max
60L, TimeUnit.SECONDS, // keepAlive
new LinkedBlockingQueue<>(100), // queue (100)
Executors.defaultThreadFactory(), // factory
new ThreadPoolExecutor.AbortPolicy() // 거부 정책
);
| 파라미터 | 역할 |
|---|---|
| corePoolSize | 평상시 스레드 |
| maximumPoolSize | 최대 스레드 |
| keepAliveTime | 유휴 정리 시간 |
| workQueue | 대기 작업 |
| handler | 거부 처리 |
Executors 는 ThreadPoolExecutor 래핑:
newFixedThreadPool(n):
new ThreadPoolExecutor(n, n, 0, MS,
new LinkedBlockingQueue<>()) // 무제한 큐
newCachedThreadPool():
new ThreadPoolExecutor(0, MAX_VALUE, 60, SEC,
new SynchronousQueue<>()) // 무제한 스레드
→ Executors 는 편의, 직접 생성은 제어
@Configuration
public class ThreadPoolExecutorConfig {
private final int cores = Runtime.getRuntime().availableProcessors();
@Bean("shipmentExecutor")
public ThreadPoolExecutor shipmentExecutor() {
return new ThreadPoolExecutor(
cores, // core: CPU 수
cores * 2, // max: 2배
60L, TimeUnit.SECONDS, // keepAlive: 1분
new LinkedBlockingQueue<>(1000),// 큐: 1000
r -> {
Thread t = new Thread(r, "shipment-" + System.nanoTime());
return t;
},
new ThreadPoolExecutor.CallerRunsPolicy() // 거부 정책
);
}
}
ThreadPoolExecutor의 핵심 파라미터 5가지는?
답:
1. corePoolSize: 기본 스레드
2. maximumPoolSize: 최대 스레드
3. keepAliveTime: 유휴 정리
4. workQueue: 작업 큐
5. rejectedExecutionHandler: 거부 정책
(+ threadFactory, unit)
corePoolSize:
평상시 유지하는 스레드 수.
- 작업 없어도 유지 (기본)
- 항상 대기
특징:
- 기본 일꾼
- 정리 안 됨 (기본)
maximumPoolSize:
최대 스레드 수.
- 큐 가득 시 max 까지 확장
- core 초과분은 임시
특징:
- 최대 한계
- 초과분은 keepAlive 후 정리
corePoolSize vs maximumPoolSize:
corePoolSize:
- 평상시
- 유지
maximumPoolSize:
- 최대 (바쁠 때)
- 초과분 임시
예:
core=4, max=10
- 평상시 4
- 바쁘면 최대 10
- 한가하면 다시 4
스레드 수 변화:
평상시: core (4)
큐 적재: core (4) + 큐
큐 가득: max 까지 (5~10)
한가: core (4) 로 복귀 (keepAlive)
→ core 와 max 사이 동적
// core == max → 고정 풀
new ThreadPoolExecutor(
10, 10, // core == max
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<>()
);
// 항상 10개 (newFixedThreadPool 과 유사)
// keepAlive 0 (정리 안 함, core == max)
@Configuration
public class CoreVsMaxConfig {
private final int cores = Runtime.getRuntime().availableProcessors();
// 변동 부하 — core < max
@Bean("variableLoad")
public ThreadPoolExecutor variableExecutor() {
return new ThreadPoolExecutor(
cores, // 평상시 (예: 8)
cores * 4, // 최대 (예: 32, 피크 시)
60L, TimeUnit.SECONDS,
new LinkedBlockingQueue<>(500),
new ThreadPoolExecutor.CallerRunsPolicy()
);
// 평상시 8, 바쁘면 32, 한가하면 8 복귀
}
// 안정 부하 — core == max (고정)
@Bean("stableLoad")
public ThreadPoolExecutor stableExecutor() {
return new ThreadPoolExecutor(
cores, cores, // 고정
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<>(1000),
new ThreadPoolExecutor.AbortPolicy()
);
}
}
corePoolSize vs maximumPoolSize 차이는?
답:
1. corePoolSize:
maximumPoolSize:
변화:
같으면:
keepAliveTime:
코어를 초과한 유휴 스레드가
정리되기까지의 시간.
동작:
- core 초과 스레드 유휴 시
- keepAliveTime 후 정리
- core 로 복귀
keepAliveTime 동작:
바쁠 때: max 까지 확장 (예: 10)
↓ (작업 감소)
유휴 스레드 발생
↓ keepAliveTime 경과
core 초과 스레드 정리 (10 → 4)
↓
core 유지 (4)
keepAliveTime:
스레드 수:
10 ┤ ╭────╮
│ ╱ ╲ (유휴, keepAlive 경과)
4 ┤────╯ ╲────── core 복귀
└──────────────────────→ 시간
바쁨 한가(정리)
core 초과분만 정리
core 는 유지 (기본)
// 기본: core 는 정리 안 됨
executor.keepAliveTime; // core 초과분만
// allowCoreThreadTimeOut(true): core 도 정리
executor.allowCoreThreadTimeOut(true);
// core 스레드도 유휴 시 정리
// 완전히 비울 수 있음
// keepAlive 60초
new ThreadPoolExecutor(
4, 10,
60L, TimeUnit.SECONDS, // 유휴 60초 후 정리
new LinkedBlockingQueue<>(100)
);
// core == max 면 keepAlive 무의미 (보통 0)
new ThreadPoolExecutor(
10, 10,
0L, TimeUnit.MILLISECONDS, // 정리할 초과분 없음
new LinkedBlockingQueue<>()
);
@Configuration
public class KeepAliveConfig {
// 변동 부하 — keepAlive 활용
@Bean
public ThreadPoolExecutor burstExecutor() {
ThreadPoolExecutor executor = new ThreadPoolExecutor(
4, // 평상시 4
20, // 피크 20
30L, TimeUnit.SECONDS, // 유휴 30초 후 정리
new LinkedBlockingQueue<>(200),
new ThreadPoolExecutor.CallerRunsPolicy()
);
// 피크 후 30초 한가하면 20 → 4 정리
// 메모리 절약
return executor;
}
// 완전 정리 (core 도)
@Bean
public ThreadPoolExecutor fullCleanup() {
ThreadPoolExecutor executor = new ThreadPoolExecutor(
4, 20, 60L, TimeUnit.SECONDS,
new LinkedBlockingQueue<>(200)
);
executor.allowCoreThreadTimeOut(true); // core 도 정리
return executor;
// 완전 유휴 시 0까지 (메모리 최소)
}
}
keepAliveTime의 역할은?
답:
1. 역할:
동작:
core 정리:
효과:
workQueue (작업 큐):
대기 작업을 저장하는 BlockingQueue.
- 코어 스레드 다 차면 적재
- 워커가 take
종류:
- LinkedBlockingQueue
- ArrayBlockingQueue
- SynchronousQueue
workQueue 종류:
LinkedBlockingQueue:
- 링크드, 선택적 크기
- 무제한 (기본) 또는 제한
ArrayBlockingQueue:
- 배열, 고정 크기
- 제한
SynchronousQueue:
- 크기 0 (직접 전달)
- 큐 안 함 (바로 스레드)
큐의 역할:
코어 다 차면:
- 작업을 큐에 적재
- 큐 가득 차면 max 확장
→ 큐가 버퍼 역할
→ 흐름 제어
// ⚠️ 무제한 큐 (LinkedBlockingQueue 기본)
new ThreadPoolExecutor(
4, 10,
60L, TimeUnit.SECONDS,
new LinkedBlockingQueue<>() // 무제한!
);
// 문제:
// - 큐 무제한 → max 도달 X (큐가 안 참)
// - 작업 쌓이면 OOM
// - max 무의미
// ✓ 제한 큐
new LinkedBlockingQueue<>(1000); // 제한
// SynchronousQueue — 큐 안 함 (직접 전달)
new ThreadPoolExecutor(
0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<>() // 크기 0
);
// 작업이 바로 스레드로 (큐 X)
// 스레드 없으면 새로 생성 (max 까지)
// newCachedThreadPool 패턴
@Configuration
public class WorkQueueConfig {
// 제한된 큐 (권장, 백프레셔)
@Bean("bounded")
public ThreadPoolExecutor boundedQueue() {
return new ThreadPoolExecutor(
4, 10, 60L, TimeUnit.SECONDS,
new LinkedBlockingQueue<>(1000), // 제한
new ThreadPoolExecutor.CallerRunsPolicy()
);
}
// ArrayBlockingQueue (고정)
@Bean("array")
public ThreadPoolExecutor arrayQueue() {
return new ThreadPoolExecutor(
4, 10, 60L, TimeUnit.SECONDS,
new ArrayBlockingQueue<>(500), // 고정 배열
new ThreadPoolExecutor.AbortPolicy()
);
}
// SynchronousQueue (직접 전달, 캐시 패턴)
@Bean("synchronous")
public ThreadPoolExecutor synchronousQueue() {
return new ThreadPoolExecutor(
0, 50, 60L, TimeUnit.SECONDS,
new SynchronousQueue<>(), // 큐 X
new ThreadPoolExecutor.AbortPolicy()
);
}
}
workQueue의 역할은?
답:
1. 역할:
종류:
무제한 주의:
SynchronousQueue:
작업 추가 흐름 (★ 핵심):
1. 코어 스레드 < corePoolSize?
→ 새 코어 스레드 생성, 실행
2. 코어 다 참?
→ 작업 큐에 적재
3. 큐도 가득 참?
→ max 까지 새 스레드 생성, 실행
4. max 도 다 차고 큐도 가득?
→ 거부 (RejectedExecutionHandler)
단계별:
[1] 코어 미만:
현재 스레드 < core
→ 새 코어 스레드 (작업 즉시 실행)
[2] 코어 충족, 큐 여유:
현재 스레드 == core
→ 큐에 적재 (대기)
[3] 큐 가득, max 미만:
큐 full + 스레드 < max
→ 새 스레드 (max 까지)
[4] max + 큐 가득:
스레드 == max + 큐 full
→ 거부
작업 추가 흐름:
작업 도착
↓
스레드 < core? ──예──→ 코어 스레드 생성 (실행)
↓ 아니오
큐 여유 있음? ──예──→ 큐에 적재
↓ 아니오 (큐 가득)
스레드 < max? ──예──→ 스레드 생성 (max 까지, 실행)
↓ 아니오 (max 도달)
거부 (RejectedExecutionHandler)
예: core=2, max=4, queue=2
작업1: 스레드 < 2 → 코어 스레드1 (실행) [스레드 1]
작업2: 스레드 < 2 → 코어 스레드2 (실행) [스레드 2]
작업3: 코어 참 → 큐 적재 [큐 1]
작업4: 코어 참 → 큐 적재 [큐 2, 가득]
작업5: 큐 가득, 스레드 < 4 → 스레드3 (실행) [스레드 3]
작업6: 큐 가득, 스레드 < 4 → 스레드4 (실행) [스레드 4]
작업7: max + 큐 가득 → 거부!
총 처리: 6개 (스레드 4 + 큐 2)
7번째: 거부
ThreadPoolExecutor executor = new ThreadPoolExecutor(
2, 4, // core 2, max 4
60L, TimeUnit.SECONDS,
new ArrayBlockingQueue<>(2), // 큐 2
new ThreadPoolExecutor.AbortPolicy()
);
// 작업 6개: 스레드 4 + 큐 2 (처리)
// 작업 7개째: RejectedExecutionException
for (int i = 0; i < 7; i++) {
final int id = i;
try {
executor.execute(() -> {
log.info("Task {} on {}", id, Thread.currentThread().getName());
sleep(1000);
});
} catch (RejectedExecutionException e) {
log.warn("Task {} rejected", id); // 7번째
}
}
@Service
public class TaskFlowExample {
private final ThreadPoolExecutor executor = new ThreadPoolExecutor(
4, // core
8, // max
60L, TimeUnit.SECONDS,
new LinkedBlockingQueue<>(100), // 큐 100
new ThreadPoolExecutor.CallerRunsPolicy()
);
public void submitShipments(List<Shipment> shipments) {
for (Shipment shipment : shipments) {
executor.execute(() -> process(shipment));
// 흐름:
// 1~4: 코어 스레드 (즉시 실행)
// 5~104: 큐 적재 (대기)
// 105~108: max 까지 스레드 (5~8)
// 109~: CallerRunsPolicy (호출자 실행)
}
// 모니터링
log.info("Pool size: {}, Queue: {}, Active: {}",
executor.getPoolSize(),
executor.getQueue().size(),
executor.getActiveCount());
}
private void process(Shipment s) { }
}
작업 추가 흐름의 정확한 순서는?
답:
1. 순서:
핵심:
추적:
거부:
헷갈림:
"코어 차면 바로 max 로 늘린다"?
→ 아니다!
정답:
코어 차면 → 큐 먼저
큐 가득 → 그제서야 max
→ 큐가 max 보다 우선
왜 큐 먼저인가:
설계 철학:
- 스레드 생성은 비쌈
- 큐에 쌓는 게 저렴
- 큐로 흡수 (버퍼)
- 정말 바쁠 때만 max 확장
→ 큐 우선 (스레드 절약)
직관 vs 실제:
직관 (틀림):
코어 참 → 스레드 늘림 (max)
→ 큐는 마지막
실제 (맞음):
코어 참 → 큐 적재
큐 가득 → 스레드 늘림 (max)
→ max 는 큐 다음
무제한 큐 함정:
LinkedBlockingQueue (무제한):
- 큐가 절대 안 참
- → max 도달 못 함
- → max 무의미
결과:
- 항상 core 만
- 작업은 무한 큐
- OOM 위험
→ max 활용하려면 제한 큐
// 무제한 큐 → max 무의미
ThreadPoolExecutor unbounded = new ThreadPoolExecutor(
2, 10, // max 10 (무의미)
60L, TimeUnit.SECONDS,
new LinkedBlockingQueue<>() // 무제한
);
// 큐 안 참 → 스레드 항상 2 (core)
// max 10 도달 안 함
// 제한 큐 → max 동작
ThreadPoolExecutor bounded = new ThreadPoolExecutor(
2, 10,
60L, TimeUnit.SECONDS,
new ArrayBlockingQueue<>(5) // 제한 5
);
// 큐 가득 차면 → max 까지 (3~10)
@Configuration
public class QueueBeforeMaxConfig {
// ❌ 무제한 큐 (max 무의미, OOM 위험)
@Bean("wrong")
public ThreadPoolExecutor wrongConfig() {
return new ThreadPoolExecutor(
4, 20, // max 20 무의미!
60L, TimeUnit.SECONDS,
new LinkedBlockingQueue<>() // 무제한 → 큐 안 참
);
// 항상 4개만, 작업 무한 큐, OOM
}
// ✓ 제한 큐 (max 동작)
@Bean("correct")
public ThreadPoolExecutor correctConfig() {
return new ThreadPoolExecutor(
4, 20, // max 20 동작
60L, TimeUnit.SECONDS,
new LinkedBlockingQueue<>(100), // 제한 100
new ThreadPoolExecutor.CallerRunsPolicy()
);
// 코어 4 → 큐 100 → max 20 → 거부 정책
}
}
왜 큐가 max보다 먼저 채워지는가?
답:
1. 핵심:
이유:
직관과 다름:
무제한 큐 함정:
거부 정책 (RejectedExecutionHandler):
max 스레드 + 큐 가득 시 동작.
내장 4가지:
- AbortPolicy
- CallerRunsPolicy
- DiscardPolicy
- DiscardOldestPolicy
거부 정책:
AbortPolicy (기본):
- RejectedExecutionException 던짐
CallerRunsPolicy:
- 호출자 스레드가 실행
- 백프레셔 (속도 조절)
DiscardPolicy:
- 조용히 버림
DiscardOldestPolicy:
- 큐의 가장 오래된 것 버림
- 새 작업 추가
// AbortPolicy — 예외
new ThreadPoolExecutor.AbortPolicy();
// → RejectedExecutionException
// CallerRunsPolicy — 호출자 실행 (백프레셔)
new ThreadPoolExecutor.CallerRunsPolicy();
// → 제출 스레드가 직접 실행 (속도 ↓)
// DiscardPolicy — 버림
new ThreadPoolExecutor.DiscardPolicy();
// → 조용히 무시
// DiscardOldestPolicy — 오래된 것 버림
new ThreadPoolExecutor.DiscardOldestPolicy();
// 커스텀 거부 정책
RejectedExecutionHandler custom = (task, executor) -> {
log.warn("작업 거부됨, 큐 크기: {}", executor.getQueue().size());
// 로깅, 알림, 재시도 등
// 또는 다른 큐에 적재
};
정책 선택:
AbortPolicy:
- 명확한 실패
- 호출자가 처리
CallerRunsPolicy:
- 백프레셔
- 속도 조절 (권장)
DiscardPolicy:
- 손실 허용
- 로그 등
DiscardOldest:
- 최신 우선
@Configuration
public class RejectionPolicyConfig {
// CallerRunsPolicy — 백프레셔 (권장)
@Bean("backpressure")
public ThreadPoolExecutor withBackpressure() {
return new ThreadPoolExecutor(
4, 10, 60L, TimeUnit.SECONDS,
new LinkedBlockingQueue<>(100),
new ThreadPoolExecutor.CallerRunsPolicy()
// 과부하 시 호출자가 실행 → 자연스러운 속도 조절
);
}
// 커스텀 — 거부 시 알림 + 대체 큐
@Bean("custom")
public ThreadPoolExecutor withCustomPolicy() {
return new ThreadPoolExecutor(
4, 10, 60L, TimeUnit.SECONDS,
new LinkedBlockingQueue<>(100),
(task, executor) -> {
log.error("작업 거부! Active: {}, Queue: {}",
executor.getActiveCount(),
executor.getQueue().size());
metricService.incrementRejected();
// 대체 처리 (예: DB 큐에 적재)
deferredQueue.offer(task);
}
);
}
private final Queue<Runnable> deferredQueue = new ConcurrentLinkedQueue<>();
}
거부 정책은?
답:
1. 거부 정책:
네 가지:
커스텀:
권장:
// 코어 스레드 미리 시작
executor.prestartCoreThread(); // 하나
executor.prestartAllCoreThreads(); // 모두
// 기본: 작업 도착 시 생성 (lazy)
// prestart: 미리 생성 (warm-up)
// 코어 스레드도 정리
executor.allowCoreThreadTimeOut(true);
// 기본: core 유지 (정리 X)
// true: core 도 keepAliveTime 후 정리
// → 완전 유휴 시 0까지
// 런타임 변경
executor.setCorePoolSize(8); // core 변경
executor.setMaximumPoolSize(16); // max 변경
executor.setKeepAliveTime(30, TimeUnit.SECONDS);
// 부하에 따라 동적 조정 가능
// 모니터링
executor.getPoolSize(); // 현재 스레드 수
executor.getActiveCount(); // 실행 중 작업 수
executor.getCompletedTaskCount(); // 완료 작업 수
executor.getTaskCount(); // 총 작업 수
executor.getQueue().size(); // 큐 크기
executor.getLargestPoolSize(); // 최대 도달 스레드 수
ForkJoinPool 의 work stealing:
- 각 스레드 자기 큐
- 한가한 스레드가 바쁜 스레드 작업 훔침
- 부하 분산
ThreadPoolExecutor 는 단일 큐
ForkJoinPool 은 분산 큐 (Phase 8)
@Service
public class ThreadPoolControl {
private final ThreadPoolExecutor executor = new ThreadPoolExecutor(
4, 10, 60L, TimeUnit.SECONDS,
new LinkedBlockingQueue<>(100)
);
@PostConstruct
public void warmup() {
// 코어 스레드 미리 시작 (첫 요청 빠르게)
executor.prestartAllCoreThreads();
}
// 모니터링
@Scheduled(fixedRate = 10000)
public void monitor() {
log.info("Pool: {}, Active: {}, Queue: {}, Completed: {}",
executor.getPoolSize(),
executor.getActiveCount(),
executor.getQueue().size(),
executor.getCompletedTaskCount());
// 큐 적체 경고
if (executor.getQueue().size() > 80) {
log.warn("큐 적체! 스케일 검토 필요");
}
}
// 동적 조정 (부하 대응)
public void scaleUp() {
executor.setMaximumPoolSize(20);
log.info("Max pool size increased to 20");
}
}
코어 스레드 제어는?
답:
1. prestart:
allowCoreThreadTimeOut:
동적 변경:
모니터링:
| Q | 핵심 답변 |
|---|---|
| 파라미터 5가지? | core/max/keepAlive/queue/handler |
| core vs max? | 평상시 vs 최대 |
| keepAliveTime? | 유휴 정리 시간 |
| workQueue? | 대기 작업 |
| 작업 흐름? | core → 큐 → max → 거부 |
| 큐 vs max 순서? | 큐가 먼저 |
| 무제한 큐? | max 무의미, OOM |
| 거부 정책? | Abort/CallerRuns/Discard/DiscardOldest |
| prestart? | 미리 생성 |
| allowCoreThreadTimeOut? | core 정리 |
Q1. 파라미터 수? → 7개 (핵심 5)
Q2. corePoolSize? → 평상시 스레드
Q3. maximumPoolSize? → 최대 스레드
Q4. keepAliveTime? → 유휴 정리 시간
Q5. workQueue? → 작업 큐
Q6. threadFactory? → 스레드 생성
Q7. handler? → 거부 정책
Q8. unit? → 시간 단위
Q9. core vs max? → 평상시 vs 최대
Q10. core == max? → 고정 풀
Q11. core 정리? → 기본 안 함
Q12. 동적 변경? → setCorePoolSize
Q13. keepAlive 역할? → 유휴 정리
Q14. 정리 대상? → core 초과분
Q15. allowCoreThreadTimeOut? → core 도 정리
Q16. workQueue 종류? → Linked/Array/Synchronous
Q17. LinkedBlockingQueue? → 무제한/제한
Q18. ArrayBlockingQueue? → 고정
Q19. SynchronousQueue? → 직접 전달
Q20. 무제한 큐 문제? → max 무의미, OOM
Q21. 큐 가득? → max 확장
Q22. 큐 우선? → max 보다 먼저
Q23. 제한 큐? → 백프레셔
Q24. prestart? → 미리 생성
Q25. prestartAll? → 모든 core
Q26. 흐름 1? → core 미만 → 코어 스레드
Q27. 흐름 2? → core 참 → 큐
Q28. 흐름 3? → 큐 가득 → max
Q29. 흐름 4? → max + 큐 가득 → 거부
Q30. 순서? → core → 큐 → max → 거부
Q31. 큐 vs max? → 큐 먼저
Q32. 왜 큐 먼저? → 스레드 절약
Q33. 직관 오류? → 코어 차면 max (X)
Q34. 무제한 큐? → max 도달 X
Q35. core=2,max=4,큐=2 → 6개 처리, 7째 거부
Q36. 스레드 생성? → core, max 단계
Q37. 큐 적재? → core 다음
Q38. 거부 시점? → max + 큐 full
Q39. 거부 정책? → max + 큐 full
Q40. AbortPolicy? → 예외 (기본)
Q41. CallerRunsPolicy? → 호출자 실행
Q42. DiscardPolicy? → 버림
Q43. DiscardOldest? → 오래된 것 버림
Q44. 커스텀? → RejectedExecutionHandler
Q45. 백프레셔? → CallerRunsPolicy
Q46. getPoolSize? → 현재 스레드
Q47. getActiveCount? → 실행 중
Q48. getQueue().size? → 큐 크기
Q49. getLargestPoolSize? → 최대 도달
Q50. 모니터링 목적? → 적체 감지
50 / 50 → ThreadPoolExecutor 마스터
45-49 → 거의 마스터
40-44 → 복습
< 40 → Unit 7.4 재학습
답:
답:
답:
답:
답:
1. 파라미터
2. 작업 흐름 (★)
3. 핵심 함정
이번 Unit에서 ThreadPoolExecutor 내부를 봤다면, 다음은 스레드 풀 종류.
🚀 Phase 7 — Executor 프레임워크 (★ 2차 정점)
✅ Unit 7.1 스레드 풀의 필요성
✅ Unit 7.2 Executor와 ExecutorService
✅ Unit 7.3 Future와 Callable
✅ Unit 7.4 ThreadPoolExecutor 내부 (★ 마스터) ← 여기
⏭ Unit 7.5 스레드 풀 종류
⏭ Unit 7.6 작업 큐와 거부 정책
⏭ Unit 7.7 스레드 풀 종료
✅ Phase 1~6 (25 Unit, 1차 정점 완료)
🚀 Phase 7 — Executor (4/7 진행) ★ 2차 정점
총: 29/35 Unit
★ 마스터 Unit — ThreadPoolExecutor 내부 완료