상세 컨텐츠

본문 제목

[Kotlin] 스케줄러에 쓰레드 적용하기

프로그래밍/Kotlin

by 웰치스짱 2023. 3. 23. 15:26

본문

반응형

 

보통 스프링에서 주기적으로 동작하는 로직이 있는경우 @Scheduled를 사용해서 특정시간 또는 날짜에 그 로직을 작동시키는 행동을 합니다.

하지만 그 로직이 오래걸릴 경우 해당 로직 종료전에 스케줄 시간이 다시 올경우 그 스케줄은 동작하지 않습니다. 왜냐하면 해당 스케줄러가 싱글 쓰레드로 동작하기 때문입니다.

 

기본적으로 Spring은 Single Thread Executor를 사용합니다. 따라서 두 개의 @Scheduled 작업이 겹치지 않습니다. 완전히 관련 없는 클래스에 있는 두 개의 @Scheduled 메서드도 모든 @Scheduled 작업을 실행하는 단일 스레드만 있기 때문에 겹치지 않습니다 .

 

또한 기본 Executor를 스레드 풀 기반 실행기로 교체하더라도 이러한 Executor는 일반적으로 이전에 예약된 인스턴스가 완료될 때까지 작업 인스턴스의 실행을 지연합니다. 이는 fixedDelay, fixedInterval 및 cron 기반 일정에 해당됩니다. 예를 들어 이 스프링 구성은 스레드 풀을 사용하는 ScheduledThreadPoolExecutor를 생성 하지만 원하는 대로 동일한 일정의 동시 인스턴스를 허용하지 않습니다.

 

따라서 아래와 같이 빈을 생성하여 별도로 설정을 해야합니다.

 

@Bean
public TaskScheduler  taskScheduler() {
    ThreadPoolTaskScheduler threadPoolTaskScheduler = new ThreadPoolTaskScheduler();
    threadPoolTaskScheduler.setPoolSize(8);
    threadPoolTaskScheduler.setThreadNamePrefix("task-scheduler");
    return threadPoolTaskScheduler;
}

 

그리고 해당 스케줄에는 아래와 같이 어노테이션을 추가합니다.

 

@EnableAsync
public class ScheduledAsyncTask {

    @Async
    @Scheduled(fixedRate = 10000)
    public void scheduleFixedRateTaskAsync() throws InterruptedException {
        // your task logic ...
    }
}

 

또 다른 방법으로는 아예 ExecutorService를 분리하는 방법입니다.

 

public class ScheduledAsyncTask implements DisposableBean {

    private final ExecutorService executorService = Executors.newFixedThreadPool(4);

    @Scheduled(fixedRate = 10000)
    public void scheduleFixedRateTaskAsync() throws InterruptedException {
        executorService.submit(() -> {
            // Expensive calculations ...
        });
    }

    @Override
    public void destroy() {
        executorService.shutdown();
    }
}

 

실제 프로그램에서는 @Bean이 관리할 수 있게 하는것이 좀 더 좋은것 같습니다.

반응형

관련글 더보기

댓글 영역