Spring Параллельный запуск Scheduler

У меня есть следующие 3 класса:

ComponantA

package mytest.spring.test.spring;

import org.apache.log4j.Logger;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

@Component
public class ComponentA {

    Logger log = Logger.getLogger(ComponentB.class);

    @Scheduled(fixedRate=2000)
    public void sayHello() {
        for(int i=1 ; i<=5 ; i++) {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            log.info("Hello from ComponentA " + i);
        }
    }
}

ComponentB

package mytest.spring.test.spring;

import org.apache.log4j.Logger;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

@Component
public class ComponentB {

    Logger log = Logger.getLogger(ComponentB.class);

    @Scheduled(fixedRate=2000)
    public void sayHello() {
        for(int i=1 ; i<=3 ; i++) {
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            log.info("Hello from ComponentB " + i);
        }
    }
}

MyApplication

package mytest.spring.test.spring;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;

@SpringBootApplication
@EnableScheduling
public class MyApplication {

    public static void main(String[] args) {
        SpringApplication.run(MyApplication.class, args);
    }
}

Когда я его выполнил, я получаю следующий вывод:

Hello from ComponentA 1
Hello from ComponentA 2
Hello from ComponentA 3
Hello from ComponentA 4
Hello from ComponentA 5
Hello from ComponentB 1
Hello from ComponentB 2
Hello from ComponentB 3
Hello from ComponentA 1
Hello from ComponentA 2
Hello from ComponentA 3
Hello from ComponentA 4
Hello from ComponentA 5
Hello from ComponentB 1
Hello from ComponentB 2
Hello from ComponentB 3
...

Мне нужно, чтобы 2 запланированных метода выполнялись параллельно, что явно не является cae в зависимости от результата, который я получаю. Я прочитал, что должно быть возможно предоставить аннотацию @Schedule с помощью специального TaskExecutor, с помощью которого должно быть возможно определить, сколько потоков мы хотим...

Я прав? Я не могу найти, как предоставить эту информацию.

Ответ 1

В документации четко указано, что:

По умолчанию будет выполняться поиск связанного определения планировщика: либо уникальный компонент TaskScheduler в контексте, либо компонент TaskScheduler именем "taskScheduler" в противном случае; такой же поиск будет также выполнен для bean-компонента ScheduledExecutorService. Если ни один из них не разрешаем, в регистраторе будет создан и использован локальный однопоточный планировщик по умолчанию.

Когда требуется больше контроля, класс @Configuration может реализовать SchedulingConfigurer. Это позволяет получить доступ к базовому экземпляру ScheduledTaskRegistrar. Например, в следующем примере демонстрируется, как настроить исполнителя, используемого для выполнения запланированных задач:

@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);
    }
}