web-dev-qa-db-fra.com

La méthode spring @Scheduled annotated fonctionne-t-elle sur différents threads?

J'ai plusieurs méthodes annotées avec @Scheduled (fixedDelay = 10000).

Dans le contexte de l'application, j'ai cette configuration basée sur les annotations:

<task:annotation-driven />

Le problème est que, parfois, l'exécution de la méthode est retardée de quelques secondes, voire de quelques minutes.

En supposant que même si une méthode prend un certain temps pour terminer son exécution, les autres méthodes seraient toujours exécutées. Donc je ne comprends pas le retard.

Y at-il un moyen de peut-être réduire ou même supprimer le retard?

55
froi

Le documentation sur la planification dit:

Si vous ne fournissez pas d'attribut pool-size, le pool de threads par défaut n'aura qu'un seul thread.

Ainsi, si vous avez beaucoup de tâches planifiées, vous devez configurer le planificateur, comme expliqué dans la documentation, pour avoir un pool avec plus de threads, afin de vous assurer qu'une tâche longue ne retarde pas toutes les autres.

44
JB Nizet

Pour être complet, le code ci-dessous montre la manière la plus simple de configurer le planificateur avec Java config:

@Configuration
@EnableScheduling
public class SpringConfiguration {

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

Lorsque plus de contrôle est souhaité, un @Configuration La classe peut implémenter SchedulingConfigurer.

49
G. Demecki

Une méthode annotée avec @Scheduled est destiné à être exécuté séparément, sur un thread différent à un moment donné.

Si vous n'avez pas fourni de TaskScheduler dans votre configuration, Spring utilisera

Executors.newSingleThreadScheduledExecutor();

qui retourne un ScheduledExecutorService qui s'exécute sur un seul thread. En tant que tel, si vous avez plusieurs @Scheduled méthodes, bien qu’elles soient planifiées, elles doivent chacune attendre que le thread se termine pour exécuter la tâche précédente. Vous risquez de recevoir des délais de plus en plus longs car la file se remplit plus rapidement qu'elle ne se vide.

Assurez-vous de configurer votre environnement de planification avec une quantité appropriée de threads.

22
Sotirios Delimanolis

vous pouvez utiliser:

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

L'annotation @ EnableScheduling fournit les informations de clé et leur résolution:

Par défaut, recherchera une définition de planificateur associée: soit un bean unique TaskScheduler dans le contexte, soit un bean TaskScheduler nommé "taskScheduler" sinon; la même recherche sera également effectuée pour un bean ScheduledExecutorService. Si aucune des deux ne peut être résolue, un planificateur par défaut local à un seul thread sera créé et utilisé dans le registraire .

Lorsque plus de contrôle est souhaité, une classe @Configuration peut implémenter SchedulingConfigurer. Cela permet d'accéder à l'instance ScheduledTaskRegistrar sous-jacente. Par exemple, l'exemple suivant montre comment personnaliser l'exécuteur utilisé pour exécuter des tâches planifiées:

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

(emphase ajoutée)

1
jgreen

ressort par défaut utilisant un seul thread pour la tâche de planification. vous pouvez utiliser @Configuration pour les implémentations de classe SchedulingConfigurer. référence: https://crmepham.github.io/spring-boot-multi-thread-scheduling/

0
zhaoyou