[Spring] Spring Scheduler의 기본 설정은 싱글 스레드이다.
원래 스프링 부트가 제공해주는 스케줄러를 쓰고 있었는데, 다른 task를 추가해야 할 일이 생겼다.
그런데 이 스케줄링이 겹치면 어떻게 될 지 궁금해졌다.
Scheduler 테스트 셋팅
먼저 Configuration이 선언된 곳에서 @EnableScheduling
을 추가해준다.
@SpringBootApplication
@EnableScheduling
public class PlaygroundApplication {
public static void main(String[] args) {
SpringApplication.run(PlaygroundApplication.class, args);
}
}
두개의 스케줄러를 등록한다.
- test1: 1초마다 수행, 5초의 작업 시간이 걸린다.
- test2: 1초마다 수행
@Component
public class TestScheduler {
@Scheduled(fixedDelay = 1000) // 1초마다 수행
public void test1() throws InterruptedException {
Thread.sleep(5000); // 5초 작업 시간
System.out.println("[" + Thread.currentThread().getName() + "] Test1 : " + LocalDateTime.now());
}
@Scheduled(fixedDelay = 1000) // 1초마다 수행
public void test2() {
System.out.println("[" + Thread.currentThread().getName() + "] Test2 : " + LocalDateTime.now());
}
}
✅ 기대되는 결과: test2는 test1의 수행과 관련 없이 1초마다 수행된다.
결과 >
의도와는 달리, test1이 끝난 뒤 test2가 실행되는 것을 알 수 있다.
원인: 스프링에서 제공하는 스케줄러는 기본적으로 싱글스레드 이다.
스프링 공식문서에서도 볼 수 있듯이, 스프링에서 제공하는 @Scheduled
는 싱글 스레드로 동작한다.
위 예제에서도 스레드 하나만 할당 된 것을 볼 수 있다.
멀티스레드로 동작하게 하려면 thread pool size를 조절해야 한다.
@Configuration
public class SchedulerConfig implements SchedulingConfigurer {
@Override
public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
ThreadPoolTaskScheduler threadPoolTaskScheduler = new ThreadPoolTaskScheduler();
threadPoolTaskScheduler.setPoolSize(10);
threadPoolTaskScheduler.initialize();
taskRegistrar.setTaskScheduler(threadPoolTaskScheduler);
}
}
설정 후엔 의도된 대로 코드가 실행 되는 것을 알 수 있다.