@Scheduled μ¬μ©ν λ μ€λ λ μ€μ
κ°μ
μ€νλ§ νλ μμν¬μμ μ 곡νλ @Scheduled μ΄λ Έν μ΄μ μ λ©μλμ μ€μΌμ€λ§ κΈ°λ₯μ λΆμ¬νλ λ° μ¬μ©λ©λλ€. κΈ°λ³Έμ μΌλ‘ @Scheduled μ΄λ Έν μ΄μ λ§μ μ¬μ©νλ©΄ μ€νλ§μ λ¨μΌ μ€λ λμμ μ€μΌμ€λ§ μμ λ€μ μμ°¨μ μΌλ‘ μ²λ¦¬νλλ°, μ΄λ νλμ μ€μΌμ€λ§ μμ μ΄ μλ£λμ΄μΌλ§ λ€μ μ€μΌμ€λ§ μμ μ΄ μ€νλ μ μλ€λ κ²μ μλ―Έν©λλ€.
λ°λΌμ λΆκ°μ μΈ μ€μ μμ΄ μ¬λ¬ κ°μ μ€μΌμ€λ¬λ₯Ό μμ±νλ©΄, μΌλΆ μμ μ΄ μμμΉ λͺ»ν μκ°μ λμν μ μμ΅λλ€.
μμ μν©μ νλ² λ³΄κ² μ΅λλ€.
@Configuration
@EnableScheduling
public class ScheduledTasks {
private final Logger log = LoggerFactory.getLogger(ScheduledTasks.class);
@Scheduled(fixedRate = 1000) // 1μ΄λ§λ€ taskAλ₯Ό μ€νν©λλ€.
public void taskA() throws InterruptedException {
Thread.sleep(10000); // 10μ΄ λμ μΌμ μ€λ¨ν©λλ€.
log.info("taskA - {} - {}", LocalDateTime.now(), Thread.currentThread().getName());
}
@Scheduled(fixedRate = 1000) // 1μ΄λ§λ€ taskBλ₯Ό μ€νν©λλ€.
public void taskB() {
// taskBμ λ‘μ§μ μ€νν©λλ€.
log.info("taskB - {} - {}", LocalDateTime.now(), Thread.currentThread().getName());
}
μμ μμμμ taskAμ taskBλ κ°κ° 1μ΄λ§λ€ μ€νλλλ‘ μ€μ λμ΄ μμ΅λλ€. κ·Έλ¬λ μμκ³Ό λ¬λ¦¬ μ€μ λ‘ λ‘κ·Έλ₯Ό νμΈν΄ 보면, taskBκ° 10μ΄μ ν λ²λ§ μ€νλλ κ²μ νμΈν μ μμ΅λλ€.
μ΄λ @Scheduled μ΄λ Έν μ΄μ μ κΈ°λ³Έ μ€μ μ΄ λ¨μΌ μ€λ λμμ μμ μ μννκΈ° λλ¬Έμ λλ€. μ΄μ λ°λΌ, taskAμ taskBλ λμΌν μ€λ λμμ μμ°¨μ μΌλ‘ μ€νλλ©°, taskAλ 10μ΄ λμ μΌμ μ€λ¨λλ―λ‘, taskBλ taskAμ μνμ΄ λλ λκΉμ§ κΈ°λ€λ €μΌ ν©λλ€. μ€μ λ‘ λ‘κ·Έμμ 'scheduling-1'μ΄λΌλ λμΌν μ€λ λμμ λ μμ μ΄ μ€νλλ κ²μ νμΈν μ μμ΅λλ€.
μ΄ λ¬Έμ λ₯Ό ν΄κ²°νκΈ° μν΄μλ λΆκ°μ μΈ μ€μ μ΄ νμνλ°, ν¬κ² λ€μκ³Ό κ°μ΄ μΈ κ°μ§ λ°©λ²μ΄ μ‘΄μ¬ν©λλ€.
- Async μ²λ¦¬
- SchedulingConfigurer ꡬν
- TaskScheduler λΉ λ±λ‘
1. Async μ²λ¦¬
μ€νλ§μ @Async μ΄λ Έν μ΄μ μ μ¬μ©νλ©΄ λ©μλκ° λ³λμ μ€λ λμμ λΉλκΈ°μ μΌλ‘ μ€νλ©λλ€. μ΄λ₯Ό ν΅ν΄ μ¬λ¬ μμ λ€μ λμμ μ²λ¦¬ν μ μκ² λ©λλ€.
@Configuration
@EnableAsync
@EnableScheduling
public class ScheduledTasks {
private final Logger log = LoggerFactory.getLogger(ScheduledTasks.class);
@Async
@Scheduled(fixedRate = 1000)
public void taskA() throws InterruptedException {
Thread.sleep(10000);
log.info("taskA - {} - {}", LocalDateTime.now(), Thread.currentThread().getName());
}
@Async
@Scheduled(fixedRate = 1000)
public void taskB() {
log.info("taskB - {} - {}", LocalDateTime.now(), Thread.currentThread().getName());
}
}
μμ μ½λμμ, taskAμ taskBλ κ°κ° 1μ΄λ§λ€ λ³λμ μ€λ λμμ λΉλκΈ°λ‘ μ€νλλλ‘ μ€μ λμ΄ μμ΅λλ€. μ΄λ κ² μ€μ νλ©΄ taskAμ μ€νμ΄ taskBμ μν₯μ μ£Όμ§ μκ² λ©λλ€. μ€ν λ‘κ·Έλ₯Ό νμΈν΄ 보면, μ€μ λ‘ taskAμ taskBκ° κ°κ° 1μ΄λ§λ€ λ 립μ μΌλ‘ λμνλ κ²μ νμΈν μ μμ΅λλ€.
μ΄λ @Async μ΄λ
Έν
μ΄μ
μ κΈ°λ³Έ μ€μ μ΄ SimpleAsyncTaskExecutorλ₯Ό μ¬μ©νκΈ° λλ¬Έμ
λλ€. νΉν taskAμ κ²½μ° μ΄μ μ€μ μμλ 10μ΄ λμ μΌμ μ€λ¨λμμ§λ§, μ΄λ² μ€μ μμλ 1μ΄λ§λ€ μλ‘μ΄ μ€λ λμμ λ
립μ μΌλ‘ μνλλ κ²μ νμΈν μ μμ΅λλ€. μ΄λ κ² λΉλκΈ°λ‘ μννλ©΄ λ³λμ μ€λ λμμ λ
립μ μΌλ‘ μμ
μ μννλ―λ‘, ν μμ
μ μ§μ°μ΄ λ€λ₯Έ μμ
μ μν₯μ λ―ΈμΉλ κ²μ λ°©μ§ν μ μμ΅λλ€.
2. SchedulingConfigurer ꡬν
SchedulingConfigurer μΈν°νμ΄μ€λ₯Ό ꡬννλ©΄, μ€μΌμ€λ¬μ λμμ λμ± μΈλΆμ μΌλ‘ μ μ΄ν μ μμ΅λλ€. μ΄λ₯Ό ν΅ν΄ μ€μΌμ€λ¬κ° μ¬μ©νλ μ€λ λ νμ ν¬κΈ°λ₯Ό μ‘°μ νκ±°λ μ€λ λμ μ΄λ¦μ λ³κ²½νλ λ±μ μμ μ μνν μ μμ΅λλ€.
@Configuration
@EnableScheduling
public class SchedulerConfig implements SchedulingConfigurer {
@Override
public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
ThreadPoolTaskScheduler threadPoolTaskScheduler = new ThreadPoolTaskScheduler();
threadPoolTaskScheduler.setPoolSize(10);
threadPoolTaskScheduler.setThreadNamePrefix("my-scheduler-");
threadPoolTaskScheduler.initialize();
taskRegistrar.setTaskScheduler(threadPoolTaskScheduler);
}
}
μ μμμμλ SchedulingConfigurer μΈν°νμ΄μ€λ₯Ό ꡬννλ SchedulerConfig ν΄λμ€κ° μ€λ λ νμ ν¬κΈ°λ₯Ό 10μΌλ‘ μ€μ νκ³ , μ€λ λ μ΄λ¦μ μ λμ¬λ₯Ό "my-scheduler-"λ‘ μ€μ νκ³ μμ΅λλ€. μ΄λ κ² νλ©΄, μ€μΌμ€λ§ μμ μ "my-scheduler-" μ λμ¬λ₯Ό κ°μ§ 10κ°μ μ€λ λμμ λμμ μ²λ¦¬λ μ μκ² λ©λλ€.
μ€ν κ²°κ³Όλ₯Ό 보면 taskAμ taskBκ° κ°κ° λ³λμ μ€λ λμμ μνλλ κ²μ μ μ μμ΅λλ€. λν λΉλκΈ° μ²λ¦¬λ₯Ό μ¬μ©νμ λμλ λ¬λ¦¬ taskAμ ν λ²μ μ€νμ΄ λλμΌ κ·Έλ€μ taskAμ μ€νμ΄ μμλλ κ²μ νμΈν μ μμ΅λλ€.
μ΄λ₯Ό ν΅ν΄, λμΌν μμ
μ λν΄μλ μμ°¨μ μΈ μ€νμ 보μ₯νλ©΄μλ, λ€λ₯Έ μμ
λ€μ λν΄μλ λ³λ ¬μ μΈ μ€νμ κ°λ₯νκ² νλ μ€μΌμ€λ§ μ€μ μ ꡬμ±ν μ μμ΅λλ€.
3. TaskScheduler λΉ λ±λ‘
TaskSchedulerλ₯Ό μ€νλ§ λΉμΌλ‘ λ±λ‘νλ λ°©λ²μ μ€μ λ°©μμ΄ κ°λ¨νλ€λ μ₯μ μ΄ μμ΅λλ€.
μ΄ λ°©λ²λ SchedulingConfigurerμ ꡬννλ κ²κ³Ό λ§μ°¬κ°μ§λ‘ μ€μΌμ€λ§ κΈ°λ₯μ νμ±ννκ³ , μ€λ λ νμ ν¬κΈ°μ μ€λ λ μ΄λ¦μ μ λμ¬λ₯Ό μ€μ νλ κ²μ λμΌν©λλ€. νμ§λ§ μ€μΌμ€λ§ μ€μ μ μ€νλ§ μ»¨ν μ΄λμ μμνμ¬ μλμΌλ‘ μ²λ¦¬ν μ μμ΅λλ€.
@Configuration
@EnableScheduling
public class SchedulerConfig {
@Bean
public TaskScheduler taskScheduler() {
ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
scheduler.setPoolSize(10);
scheduler.setThreadNamePrefix("my-scheduler-");
scheduler.initialize();
return scheduler;
}
}
μ μ½λμμλ ThreadPoolTaskSchedulerλ₯Ό μμ±νκ³ μ€λ λ νμ ν¬κΈ°λ₯Ό 10μΌλ‘ μ€μ νλ©°, μ€λ λ μ΄λ¦μ μ λμ¬λ₯Ό "my-scheduler-"λ‘ μ€μ ν ν μ€νλ§ λΉμΌλ‘ λ±λ‘νκ³ μμ΅λλ€. μ΄ μ€μ μ SchedulingConfigurer μΈν°νμ΄μ€λ₯Ό ꡬννλ λ°©λ²κ³Ό λμΌν κ²°κ³Όλ₯Ό μ 곡νμ§λ§, μ€νλ§ μ»¨ν μ΄λκ° μ€μΌμ€λ§ μ€μ μ μλμΌλ‘ μ²λ¦¬νλ―λ‘ λ³λμ μ€μ μμ΄λ μ¬λ¬ μ€μΌμ€λ§ μμ μ λ³λ ¬λ‘ μ²λ¦¬ν μ μμ΅λλ€.
μ¬κΈ°μ "λ³λμ μ€μ "μ΄λ, SchedulingConfigurerλ₯Ό ꡬννλ λ°©μμμ νμν configureTasks λ©μλλ₯Ό μ§μ ꡬννλ λ±μ μμ μ μλ―Έν©λλ€. TaskScheduler λΉ λ±λ‘ λ°©μμμλ μ΄λ° μΆκ°μ μΈ μμ μμ΄λ μ€νλ§μ΄ μ€μΌμ€λ¬λ₯Ό μλμΌλ‘ κ΄λ¦¬νκ² λ©λλ€.
μ€ν κ²°κ³Όλ₯Ό νμΈνλ©΄, SchedulingConfigurerλ₯Ό ꡬννμ λμ λμΌν κ²°κ³Όλ₯Ό λνλ΄λ κ²μ νμΈν μ μμ΅λλ€.
μ 리
μ€νλ§μ @Scheduled μ΄λ Έν μ΄μ μ μ¬μ©νλ©΄ λ©μλμ μ€μΌμ€λ§ κΈ°λ₯μ λΆμ¬ν μ μμ§λ§ κΈ°λ³Έ μ€μ μΌλ‘λ λͺ¨λ μμ μ΄ ν μ€λ λμμ μμ°¨μ μΌλ‘ μ²λ¦¬λ©λλ€. μ΄λ₯Ό ν΄κ²°νκΈ° μν΄ Async μ²λ¦¬, SchedulingConfigurer ꡬν, TaskScheduler λΉ λ±λ‘ λ±μ λ°©λ²μ μ¬μ©νμ¬ μ€μΌμ€λ§ λμμ μΈλΆμ μΌλ‘ μ μ΄ν μ μμ΅λλ€. μ΄λ₯Ό ν΅ν΄ μ¬λ¬ μμ λ€μ λμμ μ²λ¦¬νκ±°λ, μ€μΌμ€λ§ μ€μ μ μλμΌλ‘ μ²λ¦¬ν μ μμ΅λλ€.