스케줄드 스레드 풀 vs 단일 스레드 실행기
Java의 Executor 프레임워크는 멀티스레딩 작업을 체계적으로 관리할 수 있도록 다양한 실행기(Executor) 구현체를 제공합니다. 그중에서도 ScheduledThreadPool(스케줄드 스레드 풀)과 SingleThreadExecutor(단일 스레드 실행기)는 설계 목적과 동작 방식이 뚜렷하게 다르기 때문에, 애플리케이션의 요구 사항에 맞는 선택이 매우 중요합니다.
아래 비교표는 두 실행기의 핵심적인 차이점을 항목별로 정리한 것입니다.
| 번호 | 구분 | 스케줄드 스레드 풀 (Scheduled Thread Pool) | 단일 스레드 실행기 (Single Thread Executor) |
|---|---|---|---|
| 1 | 기본 개념 | 주어진 지연 시간(delay) 이후 작업을 실행하거나, 일정 주기마다 작업을 반복 실행할 수 있는 예약 기능을 갖춘 스레드 풀을 생성합니다. | 작업이 반드시 순차적으로 실행되며, 어느 시점에든 활성 상태인 작업은 최대 하나뿐임이 보장됩니다. |
| 2 | 큐(Queue) | 지연 큐(Delay Queue)를 사용하여 작업을 저장하고, 지연 시간에 따라 작업 실행을 예약합니다. | 블로킹 큐(Blocking Queue)를 사용하여 작업을 순서대로 처리합니다. |
| 3 | 스레드 수명 | 유휴(idle) 상태라도 생성 시 지정된 수만큼의 스레드를 풀에 계속 유지합니다. | 작업 처리 중 스레드가 비정상적으로 종료되면, 다음 작업을 위해 새로운 스레드를 자동으로 재생성합니다. |
| 4 | 스레드 풀 크기 | 생성 시 지정한 코어 스레드 수(corePoolSize)에 맞춰 고정된 크기로 운영됩니다. | 항상 정확히 하나의 스레드만 사용합니다. |
| 5 | 사용 사례 | 일정 시간 후 작업을 실행하거나 주기적인 반복 실행이 필요한 경우에 적합합니다. (예: 배치 작업, 로그 정리, 헬스 체크) | 작업 간 실행 순서 보장이 필요한 경우에 적합합니다. (예: Task1이 반드시 Task2보다 먼저 실행되어야 할 때) |
ScheduledThreadPool 예제
아래 예제는 10개의 스레드를 가진 스케줄드 스레드 풀을 생성한 뒤, 지연 실행과 주기적 실행을 예약하는 방법을 보여줍니다.
public class ScheduledThreadPoolExample {
public static void main(String args[]) {
ScheduledExecutorService services = Executors.newScheduledThreadPool(10);
// 10초 후 작업을 한 번 실행
services.schedule(new Task(), 10, TimeUnit.SECONDS);
// 15초 후 처음 실행되고, 이후 10초 간격으로 반복 실행
services.scheduleAtFixedRate(new Task(), 15, 10, TimeUnit.SECONDS);
}
}
public class Task implements Runnable {
@Override
public void run() {
System.out.println("In Run");
}
}SingleThreadExecutor 예제
아래 예제는 단일 스레드 실행기를 생성하고 작업을 제출(submit)하는 기본적인 방법을 보여줍니다. 여러 작업을 제출하더라도 항상 하나의 스레드가 순서대로 처리합니다.
public class Main {
public static void main(String args[]) {
ExecutorService services = Executors.newSingleThreadExecutor();
Future<?> future = services.submit(new Task());
}
}
public class Task implements Runnable {
@Override
public void run() {
System.out.println("In Run");
}
}정리
스케줄드 스레드 풀은 '언제 실행할 것인가'가 핵심입니다. 지연 실행이나 주기적 실행이 필요하다면 이것이 올바른 선택입니다. 반면 단일 스레드 실행기는 '순서 보장'이 핵심으로, 여러 작업이 동시에 실행되지 않고 제출된 순서대로 하나씩 처리되어야 하는 상황에 적합합니다. 두 실행기의 특성을 정확히 이해하고 사용하면 불필요한 동시성 문제를 예방하고 코드의 안정성을 높일 수 있습니다.