ScheduledThreadPoolExecutor
ScheduledThreadPoolExecutor (지연·주기 실행을 지원하는 쓰레드 풀)
주어진 지연 후에 명령을 실행하거나 주기적으로 실행할 수 있도록 예약 기능을 추가한 ThreadPoolExecutor예요. 여러 워커 쓰레드가 필요하거나 ThreadPoolExecutor의 확장 기능이 필요할 때 Timer보다 선호돼요.
본문
ScheduledThreadPoolExecutor는 ThreadPoolExecutor를 상속하면서, 명령을 지연 실행하거나 주기적으로 실행하도록 예약할 수 있어요.
- 지연된 작업은 활성화된 시점보다 더 일찍 실행되지는 않지만, 활성화 이후 실제로 언제 시작될지에 대한 실시간 보장은 없어요.
- 같은 실행 시점으로 예약된 작업은 제출된 순서대로(FIFO) 활성화돼요.
- 취소된 작업은 기본적으로 지연이 경과할 때까지 작업 큐에 남아 있어요. 즉시 제거하려면
setRemoveOnCancelPolicy(boolean)로 설정해요. scheduleAtFixedRate나scheduleWithFixedDelay로 예약한 주기 작업의 연속 실행은 겹치지 않아요.
ScheduledExecutorService scheduler = new ScheduledThreadPoolExecutor(2);
scheduler.schedule(() -> System.out.println("한 번 실행"), 5, TimeUnit.SECONDS);
scheduler.scheduleAtFixedRate(task, 0, 1, TimeUnit.SECONDS);
이 클래스는 고정 크기 풀처럼 동작하므로 maximumPoolSize 조정은 별 효과가 없어요. 또 corePoolSize를 0으로 만들거나 allowCoreThreadTimeOut을 쓰면 작업을 처리할 쓰레드가 없어질 수 있으니 주의해야 해요.
기본 쓰레드 팩토리는 Executors.defaultThreadFactory(), 기본 거부 처리기는 ThreadPoolExecutor.AbortPolicy예요.
이 클래스는 execute와 submit 메서드를 재정의해 내부적으로 ScheduledFuture 객체를 만들어 작업별 지연과 스케줄링을 제어해요. 하위 클래스에서도 이 메서드들을 재정의한다면 반드시 슈퍼클래스 버전을 호출해야 기능이 유지돼요. 작업 타입을 커스터마이즈하려면 보호 메서드 decorateTask를 재정의하면 돼요.
public class CustomScheduledExecutor extends ScheduledThreadPoolExecutor {
static class CustomTask<V> implements RunnableScheduledFuture<V> { ... }
protected <V> RunnableScheduledFuture<V> decorateTask(Runnable r, RunnableScheduledFuture<V> task) {
return new CustomTask<V>(r, task);
}
// ... 생성자 등 추가
}