Чи працює анотовані методи spring @Scheduled в різних потоках?


80

У мене є кілька методів, котрі коментуються @Scheduled(fixedDelay=10000).

У контексті програми у мене є така установка на основі анотацій:

<task:annotation-driven />

Проблема в тому, що іноді виконання деяких методів затримується на секунди і навіть хвилини.

Я припускаю, що навіть якщо метод займає деякий час, щоб закінчити виконання, інші методи все одно будуть виконуватися. Тому я не розумію затримки.

Чи є спосіб, можливо, зменшити або навіть усунути затримку?

Відповіді:


58

Для повноти наведений нижче код показує найпростіший можливий спосіб налаштування планувальника за допомогою налаштування Java:

@Configuration
@EnableScheduling
public class SpringConfiguration {

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

Коли потрібно більше контролю, @Configurationклас може реалізувати SchedulingConfigurer.


4
Оскільки Executorінтерфейс не має shutdown()методу, я думаю, його краще використовувати ExecutorServiceяк тип повернення, щоб зробити визначення компонента правильним. Або Spring виявить фактичний тип квасолі під час виконання?
Володимир Вагайцев

1
Конфігурація XML<task:scheduler id="taskScheduler" pool-size="5"/>
whoami

1
Дивіться тут приклад SchedulingConfigurer
хрусткий

1
Не працює разом із Spring autoconfig: компонент "taskScheduler", визначений у ресурсі шляху до класу [org / springframework / boot / autoconfigure / task / TaskSchedulingAutoConfiguration.class], не може бути зареєстрований. Біб з такою назвою вже був визначений у ресурсі шляху до класу ...
Філ

52

У документації щодо планування планується:

Якщо ви не надаєте атрибут розміру пулу, пул потоків за замовчуванням матиме лише один потік.

Отже, якщо у вас багато запланованих завдань, вам слід налаштувати планувальник, як пояснюється в документації, на пул із більшою кількістю потоків, щоб переконатися, що одне довге завдання не затримує всі інші.


20
Так само, як fyi: Це не допомагає надати лише посилання на загальні документи та сказати, що ви "налаштували його" ... Надання прикладу нескінченно корисніше. Я проголосував за г. Відповідь Демецького нижче, а не ваша саме з цієї причини ... Просто поради, щоб просунутися вперед
nterry

Цитована документація стосується того, task:schedulerякий має pool-sizeпараметр. Чи стосується це @Scheduledанотації, яка не має параметрів, пов’язаних з пулом?
Девід Сороко,

@DavidSoroko Я так вважаю.
пт

34

Метод, котрий коментується @Scheduled , призначений для запуску окремо, в інший потік в даний момент часу.

Якщо ви не вказали TaskSchedulerу своїй конфігурації, використовуватиме Spring

Executors.newSingleThreadScheduledExecutor();

який повертає ScheduledExecutorServiceте, що працює в одному потоці. Як такий, якщо у вас кілька@Scheduled методів, хоча вони заплановані, кожному з них потрібно почекати, поки потік завершить виконання попереднього завдання. Ви можете продовжувати збільшувати та збільшувати затримки, оскільки черга заповнюється швидше, ніж вичерпується.

Обов’язково налаштуйте середовище планування з відповідною кількістю потоків.


Посилання на весняну документацію?
Девід Сороко,

@DavidSoroko Це не відразу очевидно в Javadoc. Це простіше побачити у вихідному коді. @Scheduled(та @EnableScheduling) обробляється шляхом реєстрації ScheduledAnnotationBeanPostProcessor. Цей поштовий процесор використовує ScheduledTaskRegistrar значення, яке за замовчуванням є однопотоковимScheduledExecutorService .
Sotirios Delimanolis

4
Я думаю, ви занадто добрі - цього взагалі немає в документації. Щодо вихідного коду - він може змінюватися від випуску до випуску.
Девід Сороко,

23

ОНОВИТИ 2019

Існує також властивість, яку ви можете встановити у файлі властивостей програми, яка збільшує розмір пулу:

spring.task.scheduling.pool.size=10

Здається, там з Spring Boot 2.1.0.


2
Це єдиний спосіб це зробити, якщо весняна версія завантаження> = 2.0. Перевизначити taskScheduler () марно
Жан

10

Ви можете використовувати:

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

2
Я думаю , що це хороша практика для виклику taskScheduler.initialize();до повернення примірникаtaskScheduler
Orby

6

@EnableScheduling анотацій містить ключову інформацію та способи її вирішення:

За замовчуванням буде здійснюватися пошук відповідного визначення планувальника: або унікальний компонент TaskScheduler у контексті, або компонент TaskScheduler з іменем "taskScheduler", інакше; той самий пошук також буде виконаний для компонента 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);
     }
 }

(курсив додано)


0

За допомогою файлу XML додайте рядки нижче.

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

-1

пружина за замовчуванням з використанням одного потоку для завдання розкладу. Ви можете використовувати @Configuration для реалізації класу SchedulingConfigurer. посилання:https://crmepham.github.io/spring-boot-multi-thread-scheduling/

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.