[java] Spring @Scheduled 주석이 달린 메소드는 다른 스레드에서 실행됩니까?

주석이 달린 몇 가지 방법이 있습니다 @Scheduled(fixedDelay=10000).

애플리케이션 컨텍스트에서 다음과 같은 주석 기반 설정이 있습니다.

<task:annotation-driven />

문제는 때때로 일부 메서드 실행이 몇 초에서 몇 분까지 지연된다는 것입니다.

메서드가 실행을 완료하는 데 시간이 걸리더라도 다른 메서드는 계속 실행될 것이라고 가정하고 있습니다. 그래서 나는 지연을 이해하지 못합니다.

지연을 줄이거 나 제거 할 수있는 방법이 있습니까?



답변

완전성을 위해 아래 코드는 java 구성으로 스케줄러를 구성하는 가장 간단한 방법을 보여줍니다.

@Configuration
@EnableScheduling
public class SpringConfiguration {

    @Bean(destroyMethod = "shutdown")
    public Executor taskScheduler() {
        return Executors.newScheduledThreadPool(5);
    }
    ...

더 많은 제어가 필요한 경우 @Configuration클래스는 SchedulingConfigurer.


답변

일정에 대한 문서는 말합니다 :

풀 크기 속성을 제공하지 않으면 기본 스레드 풀에는 단일 스레드 만 있습니다.

따라서 예약 된 작업이 많은 경우 문서에 설명 된대로 더 많은 스레드가있는 풀을 갖도록 스케줄러를 구성하여 하나의 긴 작업이 다른 모든 작업을 지연시키지 않도록해야합니다.


답변

로 주석이 달린 메서드 @Scheduled는 한 번에 다른 스레드에서 개별적으로 실행됩니다.

TaskScheduler구성에를 제공하지 않은 경우 Spring은

Executors.newSingleThreadScheduledExecutor();

ScheduledExecutorService단일 스레드에서 실행 되는을 반환합니다 . 따라서 여러 @Scheduled메서드 가있는 경우 예약 된 경우에도 각각 스레드가 이전 작업 실행을 완료 할 때까지 기다려야합니다. 대기열이 비워지는 것보다 더 빨리 채워 지므로 계속 더 크고 더 큰 지연이 발생할 수 있습니다.

적절한 양의 스레드를 사용하여 스케줄링 환경을 구성해야합니다.


답변

2019 업데이트

풀 크기를 늘리는 애플리케이션 속성 파일에서 설정할 수있는 속성도 있습니다.

spring.task.scheduling.pool.size=10

Spring Boot 2.1.0부터있는 것 같습니다.


답변

당신이 사용할 수있는:

@Bean()
public  ThreadPoolTaskScheduler  taskScheduler(){
    ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler();
    taskScheduler.setPoolSize(2);
    return  taskScheduler;
}


답변

@EnableScheduling 주석은 키 정보 및 해결 방법을 제공합니다 :

기본적으로는 연관된 스케줄러 정의를 검색합니다. 컨텍스트에서 고유 한 TaskScheduler 빈이거나 그렇지 않은 경우 “taskScheduler”라는 TaskScheduler 빈입니다. ScheduledExecutorService 빈에 대해서도 동일한 검색이 수행됩니다. 둘 중 어느 것도 해결할 수없는 경우 로컬 단일 스레드 기본 스케줄러가 생성되어 등록 기관 내에서 사용됩니다 .

더 많은 제어가 필요한 경우 @Configuration 클래스가 SchedulingConfigurer를 구현할 수 있습니다. 이를 통해 기본 ScheduledTaskRegistrar 인스턴스에 액세스 할 수 있습니다. 예를 들어 다음 예제는 예약 된 작업을 실행하는 데 사용되는 Executor를 사용자 지정하는 방법을 보여줍니다.

 @Configuration
 @EnableScheduling
 public class AppConfig implements SchedulingConfigurer {

     @Override
     public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
         taskRegistrar.setScheduler(taskExecutor());
     }

     @Bean(destroyMethod="shutdown")
     public Executor taskExecutor() {
         return Executors.newScheduledThreadPool(100);
     }
 }

(강조 추가됨)


답변

XML 파일을 사용하여 아래 줄을 추가하십시오 ..

<task:scheduler id="taskScheduler" pool-size="15" />
<task:scheduled-tasks scheduler="taskScheduler" >
....
</task:scheduled-tasks>