Используются ли spring @Scheduled аннотированные методы для разных потоков?
У меня есть несколько методов с аннотацией @Scheduled(fixedDelay=10000)
.
В контексте приложения у меня есть эта настройка на основе аннотаций:
<task:annotation-driven />
Проблема в том, что иногда выполнение некоторых методов задерживается на секунды и даже минуты.
Я предполагаю, что даже если метод занимает некоторое время, чтобы завершить выполнение, другие методы все равно будут выполняться. Так что я не понимаю задержки.
Есть ли способ уменьшить или даже убрать задержку?
Ответы
Ответ 1
Документация о расписании гласит:
Если вы не укажете атрибут размера пула, пул потоков по умолчанию будет иметь только один поток.
Поэтому, если у вас много запланированных задач, вы должны настроить планировщик, как описано в документации, на наличие пула с большим количеством потоков, чтобы одна длинная задача не задерживала все остальные.
Ответ 2
Для полноты кода ниже показан самый простой способ настройки планировщика с помощью java config:
@Configuration
@EnableScheduling
public class SpringConfiguration {
@Bean(destroyMethod = "shutdown")
public Executor taskScheduler() {
return Executors.newScheduledThreadPool(5);
}
...
Когда требуется больше управления, класс @Configuration
может реализовать SchedulingConfigurer
.
Ответ 3
Метод, аннотированный с помощью @Scheduled
, предназначен для запуска отдельно, в другом потоке в момент времени.
Если вы не указали TaskScheduler
в своей конфигурации, Spring будет использовать
Executors.newSingleThreadScheduledExecutor();
который возвращает ScheduledExecutorService
, который выполняется в одном потоке. Таким образом, если у вас несколько методов @Scheduled
, хотя они и запланированы, каждый из них должен дождаться завершения потока для выполнения предыдущей задачи. Вы можете продолжать получать большие и большие задержки, так как очередь заполняется быстрее, чем она освобождается.
Убедитесь, что вы настроили среду планирования с соответствующим количеством потоков.
Ответ 4
вы можете использовать:
@Bean()
public ThreadPoolTaskScheduler taskScheduler(){
ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler();
taskScheduler.setPoolSize(2);
return taskScheduler;
}
Ответ 5
Аннотация @EnableScheduling предоставляет ключевую информацию и способы ее решения:
По умолчанию будет выполняться поиск соответствующего определения планировщика: либо уникальный компонент 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);
}
}
(акцент добавлен)
Ответ 6
пружина по умолчанию, использующая одну нить для задания расписания. Вы можете использовать @Configuration для реализации классов SchedulingConfigurer. ссылка: https://crmepham.github.io/spring-boot-multi-thread-scheduling/